Data Exploration and Wrangling
The first step in performing any data analysis is to explore the data.
For example, we might want to better understand the variables included in the data, as we may learn about important details about the data that we should keep in mind as we try to predict our outcome variable.
First, let’s just get a general sense of our data. We can do that using the glimpse() function of the dplyr package (it is also in the tibble package).
We will also use the %>% pipe, which can be used to define the input for later sequential steps.
This will make more sense when we have multiple sequential steps using the same data object.
To use the pipe notation we need to install and load dplyr as well.
For example, here we start with pm data object and “pipe” the object into as input into the glimpse() function. The output is is an overview of what is in the pm object such as the number of rows and columns, all the column names, the data types for each column and the first view values in each column. The output below is scrollable so you can see everything from the glimpse() function.
# Scroll through the output!
pm %>%
dplyr::glimpse()
Rows: 876
Columns: 50
$ id <dbl> 1003.001, 1027.000, 1033.100, 1049.100,...
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.6590...
$ fips <dbl> 1003, 1027, 1033, 1049, 1055, 1069, 107...
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763,...
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.96...
$ state <chr> "Alabama", "Alabama", "Alabama", "Alaba...
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb",...
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals",...
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772,...
$ zcta <dbl> 36532, 36251, 35660, 35962, 35901, 3630...
$ zcta_area <dbl> 190980522, 374132430, 16716984, 2038362...
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, ...
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5....
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.867...
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.231...
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.0316...
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.9730...
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 201...
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 10...
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489,...
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193,...
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411...
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626...
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959,...
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155,...
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843,...
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.214...
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894,...
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.353...
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979,...
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, ...
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, ...
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665,...
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.0...
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.3...
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920,...
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.3308...
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.7...
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2....
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1...
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37....
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23....
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0...
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, ...
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7...
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5,...
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61....
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333,...
We can see that there are 876 monitors (rows) and that we have 50 total variables (columns) - one of which is the outcome variable. In this case, the outcome variable is called value.
Notice that some of the variables that we would think of as factors (or categorical data) are currently of class character as indicated by the <chr> just to the right of the column names/variable names in the glimpse() output. This means that the variable values are character strings, such as words or phrases.
The other variables are of class <dbl>, which stands for double precision which indicates that the are numeric and that they have decimal values. In contrast, one could have integer values which would not allow for decimal numbers. Here is a link for more information on double precision numeric values.
Another common data class is factor which is abbreviated like this: <fct>. A factor is something that has unique levels but there is no appreciable order to the levels. For example we can have a numeric value that is just an id that we want to be interpreted as just a unique level and not as the number that it would typically indicate. This would be useful for several of our variables:
- the monitor ID (
id)
- the Federal Information Processing Standard number for the county where the monitor was located (
fips)
- the zip code tabulation area (
zcta)
None of the values actually have any real numeric meaning, so we want to make sure that R does not interpret them as if they do.
So let’s convert these variables into factors. We can do this using the across() function of the dplyr package and the as.factor() base function. The across() function has two main arguments: (i) the columns you want to operate on and (ii) the function or list of functions to apply to each column.
In this case, we are also using the magrittr assignment pipe or double pipe that looks like this %<>% of the magrittr package. This allows us use the pm data as input, but also reassigns the output to the same data object name.
# Scroll through the output!
pm %<>%
mutate(across(c(id, fips, zcta), as.factor))
glimpse(pm)
Rows: 876
Columns: 50
$ id <fct> 1003.001, 1027.0001, 1033.1002, 1049.10...
$ value <dbl> 9.597647, 10.800000, 11.212174, 11.6590...
$ fips <fct> 1003, 1027, 1033, 1049, 1055, 1069, 107...
$ lat <dbl> 30.49800, 33.28126, 34.75878, 34.28763,...
$ lon <dbl> -87.88141, -85.80218, -87.65056, -85.96...
$ state <chr> "Alabama", "Alabama", "Alabama", "Alaba...
$ county <chr> "Baldwin", "Clay", "Colbert", "DeKalb",...
$ city <chr> "Fairhope", "Ashland", "Muscle Shoals",...
$ CMAQ <dbl> 8.098836, 9.766208, 9.402679, 8.534772,...
$ zcta <fct> 36532, 36251, 35660, 35962, 35901, 3630...
$ zcta_area <dbl> 190980522, 374132430, 16716984, 2038362...
$ zcta_pop <dbl> 27829, 5103, 9042, 8300, 20045, 30217, ...
$ imp_a500 <dbl> 0.01730104, 1.96972318, 19.17301038, 5....
$ imp_a1000 <dbl> 1.4096021, 0.8531574, 11.1448962, 3.867...
$ imp_a5000 <dbl> 3.3360118, 0.9851479, 15.1786154, 1.231...
$ imp_a10000 <dbl> 1.9879187, 0.5208189, 9.7253870, 1.0316...
$ imp_a15000 <dbl> 1.4386207, 0.3359198, 5.2472094, 0.9730...
$ county_area <dbl> 4117521611, 1564252280, 1534877333, 201...
$ county_pop <dbl> 182265, 13932, 54428, 71109, 104430, 10...
$ log_dist_to_prisec <dbl> 4.648181, 7.219907, 5.760131, 3.721489,...
$ log_pri_length_5000 <dbl> 8.517193, 8.517193, 8.517193, 8.517193,...
$ log_pri_length_10000 <dbl> 9.210340, 9.210340, 9.274303, 10.409411...
$ log_pri_length_15000 <dbl> 9.630228, 9.615805, 9.658899, 11.173626...
$ log_pri_length_25000 <dbl> 11.32735, 10.12663, 10.15769, 11.90959,...
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 8.611945, 7.310155,...
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 9.735569, 8.585843,...
$ log_prisec_length_5000 <dbl> 10.815042, 10.170878, 11.770407, 10.214...
$ log_prisec_length_10000 <dbl> 11.88680, 11.40554, 12.84066, 11.50894,...
$ log_prisec_length_15000 <dbl> 12.205723, 12.042963, 13.282656, 12.353...
$ log_prisec_length_25000 <dbl> 13.41395, 12.79980, 13.79973, 13.55979,...
$ log_nei_2008_pm25_sum_10000 <dbl> 0.318035438, 3.218632928, 6.573127301, ...
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967358961, 3.218632928, 6.581917457, ...
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 3.218633, 6.875900, 4.887665,...
$ log_nei_2008_pm10_sum_10000 <dbl> 1.35588511, 3.31111648, 6.69187313, 0.0...
$ log_nei_2008_pm10_sum_15000 <dbl> 2.26783411, 3.31111648, 6.70127741, 3.3...
$ log_nei_2008_pm10_sum_25000 <dbl> 5.628728, 3.311116, 7.148858, 5.171920,...
$ popdens_county <dbl> 44.265706, 8.906492, 35.460814, 35.3308...
$ popdens_zcta <dbl> 145.716431, 13.639555, 540.887040, 40.7...
$ nohs <dbl> 3.3, 11.6, 7.3, 14.3, 4.3, 5.8, 7.1, 2....
$ somehs <dbl> 4.9, 19.1, 15.8, 16.7, 13.3, 11.6, 17.1...
$ hs <dbl> 25.1, 33.9, 30.6, 35.0, 27.8, 29.8, 37....
$ somecollege <dbl> 19.7, 18.8, 20.9, 14.9, 29.2, 21.4, 23....
$ associate <dbl> 8.2, 8.0, 7.6, 5.5, 10.1, 7.9, 7.3, 8.0...
$ bachelor <dbl> 25.3, 5.5, 12.7, 7.9, 10.0, 13.7, 5.9, ...
$ grad <dbl> 13.5, 3.1, 5.1, 5.8, 5.4, 9.8, 2.0, 8.7...
$ pov <dbl> 6.1, 19.5, 19.0, 13.8, 8.8, 15.6, 25.5,...
$ hs_orless <dbl> 33.3, 64.6, 53.7, 66.0, 45.4, 47.2, 61....
$ urc2013 <dbl> 4, 6, 4, 6, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ urc2006 <dbl> 5, 6, 4, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, ...
$ aod <dbl> 37.36364, 34.81818, 36.00000, 33.08333,...
Great! Now we can see that these variables are now factors as indicated by <fct> after the variable name.
skim package
The skim() function of the skimr package is also really helpful for getting a general sense of your data. By design, it provides summary statistics about variables in the data set.
Notice how there is a column called n_missing about the number of values that are missing.
This is also indicated by the complete_rate variable (or missing/number of observations).
In our data set, it looks like our data do not contain any missing data.
Also notice how the function provides separate tables of summary statistics for each data type: character, factor and numeric.
Next, the n_unqiue column shows us the number of unique values for each of our columns. We can see that there are 49 states represented in the data.
We can see that for many variables there are many low values as the distribution shows two peaks, one near zero and another with a higher value.
This is true for the imp variables (measures of development), the nei variables (measures of emission sources) and the road density variables.
We can also see that the range of some of the variables is very large, in particular the area and population related variables.
Let’s take a look to see which states are included using the distinct() function of the dplyr package:
pm %>%
dplyr::distinct(state)
Scroll through the output:
It looks like “District of Columbia” is being included as a state. We can see that Alaska and Hawaii are not included in the data.
Let’s also take a look to see how many monitors there are in a few cities. We can use the filter() function of the dplyr package to do so. For example, let’s look at Albuquerque, New Mexico.
pm %>% dplyr::filter(city == "Albuquerque")
# A tibble: 2 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 3500~ 5.98 35001 35.1 -107. New ~ Berna~ Albu~ 10.1 87109 26199125
2 3500~ 5.91 35001 35.1 -107. New ~ Berna~ Albu~ 10.1 87108 15224438
# ... with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
We can see that there were only two monitors in the city of Albuquerque in 2006. Let’s compare this with Baltimore.
pm %>% dplyr::filter(city == "Baltimore")
# A tibble: 5 x 50
id value fips lat lon state county city CMAQ zcta zcta_area
<fct> <dbl> <fct> <dbl> <dbl> <chr> <chr> <chr> <dbl> <fct> <dbl>
1 2451~ 12.2 24510 39.3 -76.6 Mary~ Balti~ Balt~ 10.9 21251 461424
2 2451~ 12.5 24510 39.3 -76.7 Mary~ Balti~ Balt~ 10.9 21215 17645223
3 2451~ 12.8 24510 39.3 -76.5 Mary~ Balti~ Balt~ 10.9 21224 24539976
4 2451~ 14.3 24510 39.2 -76.6 Mary~ Balti~ Balt~ 10.9 21226 25718732
5 2451~ 13.3 24510 39.3 -76.6 Mary~ Balti~ Balt~ 10.9 21202 4111039
# ... with 39 more variables: zcta_pop <dbl>, imp_a500 <dbl>, imp_a1000 <dbl>,
# imp_a5000 <dbl>, imp_a10000 <dbl>, imp_a15000 <dbl>, county_area <dbl>,
# county_pop <dbl>, log_dist_to_prisec <dbl>, log_pri_length_5000 <dbl>,
# log_pri_length_10000 <dbl>, log_pri_length_15000 <dbl>,
# log_pri_length_25000 <dbl>, log_prisec_length_500 <dbl>,
# log_prisec_length_1000 <dbl>, log_prisec_length_5000 <dbl>,
# log_prisec_length_10000 <dbl>, log_prisec_length_15000 <dbl>,
# log_prisec_length_25000 <dbl>, log_nei_2008_pm25_sum_10000 <dbl>,
# log_nei_2008_pm25_sum_15000 <dbl>, log_nei_2008_pm25_sum_25000 <dbl>,
# log_nei_2008_pm10_sum_10000 <dbl>, log_nei_2008_pm10_sum_15000 <dbl>,
# log_nei_2008_pm10_sum_25000 <dbl>, popdens_county <dbl>,
# popdens_zcta <dbl>, nohs <dbl>, somehs <dbl>, hs <dbl>, somecollege <dbl>,
# associate <dbl>, bachelor <dbl>, grad <dbl>, pov <dbl>, hs_orless <dbl>,
# urc2013 <dbl>, urc2006 <dbl>, aod <dbl>
There were in contrast five monitors for the city of Baltimore, despite the fact that if we take a look at the land area and population of the counties for Blatimore City and Albuquerque, we can see that they had very similar land area and populations.
pm %>%
dplyr::filter(city == "Baltimore") %>%
select(county_area:county_pop)
# A tibble: 5 x 2
county_area county_pop
<dbl> <dbl>
1 209643241 620961
2 209643241 620961
3 209643241 620961
4 209643241 620961
5 209643241 620961
pm %>%
dplyr::filter(city == "Albuquerque") %>%
select(county_area:county_pop)
# A tibble: 2 x 2
county_area county_pop
<dbl> <dbl>
1 3006530549 662564
2 3006530549 662564
In fact, the county containing Albuerque had a larger population. Thus the measurements for Albuquerque were not as thorough as they were for Baltimore.
This may be due to the fact that the monitor values were lower in Albuquerque. It is interesting to note here that the CMAQ values are quite similar for both cities.
Evaluate correlation
In prediction analyses, it is also useful to evaluate if any of the variables are correlated. Why should we care about this?
If we are using a linear regression to model our data then we might run into a problem called multicolinearity which can lead us to misinterpret what is really predictive of our outcome variable. This phenomenon occurs when the predictor variables actually predict one another. See this case study for a deeper explanation about this.
Another reason we should look out for correlation is that we don’t want to include redundant variables. This can add unnecessary noise to our algorithm causing a reduction in prediction accuracy and it can cause our algorithm to be unnecessarily slower. Finally, it can also make it difficult to interpret what variables are actually predictive.
Intuitively we can expect some of our variables to be correlated.
Let’s first take a look at all of our numeric variables with thecorrplot package: The corrplot package is another option to look at correlation among possible predictors, and particularly useful if we have many predictors.
First, we calculate the Pearson correlation coefficients between all features pairwise using the cor() function of the stats package (which is loaded automatically). Then we use the corrplot::corrplot() function.
PM_cor <- cor(pm %>% dplyr::select_if(is.numeric))
corrplot::corrplot(PM_cor, tl.cex = 0.5)
The tl.cex = 0.5 argument controls the size of the text label.
We can also plot the absolute value of the Pearson correlation coefficients using the abs() function from base R and change the order of the columns.
corrplot(abs(PM_cor), order = "hclust", tl.cex = 0.5, cl.lim = c(0, 1))

There are several options for ordering the variables. See here for more options. Here we will use the “hclust” option for ordering by hierarchical clustering - which will order the variables by how similar they are to one another.
The cl.lim = c(0, 1) argument limits the color label to be between 0 and 1.
We can see that the development variables (imp) variables are correlated with each other as we might expect. We also see that the road density variables seem to be correlated with each other, and the emission variables seem to be correlated with each other.
Also notice that none of the predictors are highly correlated with our outcome variable (value).
We can take also take a closer look using the ggcorr() function and the ggpairs() function of the GGally package.
To select our variables of interest we can use the select() function with the contains() function of the tidyr package.
First let’s look at the imp/development variables. We can change the default color palette (palette = "RdBu") and add on correlation coefficients to the plot (label = TRUE).
select(pm, contains("imp")) %>%
ggcorr(palette = "RdBu", label = TRUE)

select(pm, contains("imp")) %>%
ggpairs()

Indeed, we can see that imp_a1000 and imp_a500 are highly correlated, as well as imp_a10000, imp_a15000.
Next, let’s take a look at the road density data:
select(pm, contains("pri")) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

We can see that many of the road density variables are highly correlated with one another, while others are less so.
Finally let’s look at the emission variables.
select(pm, contains("nei")) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

select(pm, contains("nei")) %>%
ggpairs()

We would also expect the population density data might correlate with some of these variables. Let’s take a look.
pm %>%
select(log_nei_2008_pm25_sum_10000, popdens_county,
log_pri_length_10000, imp_a10000) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

pm %>%
select(log_nei_2008_pm25_sum_10000, popdens_county,
log_pri_length_10000, imp_a10000, county_pop) %>%
ggpairs()

Interesting, so these variables don’t appear to be highly correlated, therefore we might need variables from each of the categories to predict our monitor PM2.5 pollution values.
Because some variables in our data have extreme values, it might be good to take a log transformation. This can affect our estimates of correlation.
pm %>%
mutate(log_popdens_county= log(popdens_county)) %>%
select(log_nei_2008_pm25_sum_10000, log_popdens_county,
log_pri_length_10000, imp_a10000) %>%
ggcorr(palette = "RdBu", hjust = .85, size = 3,
layout.exp=2, label = TRUE)

pm %>%
mutate(log_popdens_county= log(popdens_county)) %>%
mutate(log_pop_county = log(county_pop)) %>%
select(log_nei_2008_pm25_sum_10000, log_popdens_county,
log_pri_length_10000, imp_a10000, log_pop_county) %>%
ggpairs()

Indeed this increased the correlation, but variables from each of these categories may still prove to be useful for prediction.
Now that we have a sense of what our data are, we can get started with building a machine learning model to predict air pollution.
Data Visualization
Our main question for this case study was:
Can we predict annual average air pollution concentrations at the granularity of zip code regional levels using predictors such as data about population density, urbanization, road density, as well as, satellite pollution data and chemical modeling data?
Thus far, we have build a machine learning (ML) model to predict fine particulate matter air pollution levels based on our predictor variables (or features).
Now, let’s make a plot of our predicted outcome values (\(\hat{Y}\)) and actual outcome values \(Y\) we observed.
First, let’s start by making a plot of our monitors. To do this, we will use the following packages to create a map of the US:
sf - the simple features package helps to convert geographical coordinates into geometry variables which are useful for making 2D plots
maps - this package contains geographical outlines and plotting functions to create plots with maps
rnaturalearth- this allows for easy interaction with map data from Natural Earth which is a public domain map dataset
rgeos - this package interfaces with the Geometry Engine-Open Source (GEOS) which is also helpful for coordinate conversion
We will start with getting an outline of the US with the ne_countries() function of the rnaturalearth package which will return polygons of the countries in the Natural Earth dataset.
world <- ne_countries(scale = "medium", returnclass = "sf")
glimpse(world)
Rows: 241
Columns: 64
$ scalerank <int> 3, 1, 1, 1, 1, 3, 3, 1, 1, 1, 3, 1, 5, 3, 1, 1, 1, 1, 1,...
$ featurecla <chr> "Admin-0 country", "Admin-0 country", "Admin-0 country",...
$ labelrank <dbl> 5, 3, 3, 6, 6, 6, 6, 4, 2, 6, 4, 4, 5, 6, 6, 2, 4, 5, 6,...
$ sovereignt <chr> "Netherlands", "Afghanistan", "Angola", "United Kingdom"...
$ sov_a3 <chr> "NL1", "AFG", "AGO", "GB1", "ALB", "FI1", "AND", "ARE", ...
$ adm0_dif <dbl> 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0,...
$ level <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
$ type <chr> "Country", "Sovereign country", "Sovereign country", "De...
$ admin <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ adm0_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ geou_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ geounit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ gu_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ su_dif <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ subunit <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ su_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ brk_diff <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
$ name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ name_long <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ brk_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ brk_name <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ brk_group <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ abbrev <chr> "Aruba", "Afg.", "Ang.", "Ang.", "Alb.", "Aland", "And."...
$ postal <chr> "AW", "AF", "AO", "AI", "AL", "AI", "AND", "AE", "AR", "...
$ formal_en <chr> "Aruba", "Islamic State of Afghanistan", "People's Repub...
$ formal_fr <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ note_adm0 <chr> "Neth.", NA, NA, "U.K.", NA, "Fin.", NA, NA, NA, NA, "U....
$ note_brk <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Multiple cl...
$ name_sort <chr> "Aruba", "Afghanistan", "Angola", "Anguilla", "Albania",...
$ name_alt <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ mapcolor7 <dbl> 4, 5, 3, 6, 1, 4, 1, 2, 3, 3, 4, 4, 1, 7, 2, 1, 3, 1, 2,...
$ mapcolor8 <dbl> 2, 6, 2, 6, 4, 1, 4, 1, 1, 1, 5, 5, 2, 5, 2, 2, 1, 6, 2,...
$ mapcolor9 <dbl> 2, 8, 6, 6, 1, 4, 1, 3, 3, 2, 1, 1, 2, 9, 5, 2, 3, 5, 5,...
$ mapcolor13 <dbl> 9, 7, 1, 3, 6, 6, 8, 3, 13, 10, 1, NA, 7, 11, 5, 7, 4, 8...
$ pop_est <dbl> 103065, 28400000, 12799293, 14436, 3639453, 27153, 83888...
$ gdp_md_est <dbl> 2258.0, 22270.0, 110300.0, 108.9, 21810.0, 1563.0, 3660....
$ pop_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ lastcensus <dbl> 2010, 1979, 1970, NA, 2001, NA, 1989, 2010, 2010, 2001, ...
$ gdp_year <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ economy <chr> "6. Developing region", "7. Least developed region", "7....
$ income_grp <chr> "2. High income: nonOECD", "5. Low income", "3. Upper mi...
$ wikipedia <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ fips_10 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ iso_a2 <chr> "AW", "AF", "AO", "AI", "AL", "AX", "AD", "AE", "AR", "A...
$ iso_a3 <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", ...
$ iso_n3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", ...
$ un_a3 <chr> "533", "004", "024", "660", "008", "248", "020", "784", ...
$ wb_a2 <chr> "AW", "AF", "AO", NA, "AL", NA, "AD", "AE", "AR", "AM", ...
$ wb_a3 <chr> "ABW", "AFG", "AGO", NA, "ALB", NA, "ADO", "ARE", "ARG",...
$ woe_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ adm0_a3_is <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALA", "AND", "ARE", ...
$ adm0_a3_us <chr> "ABW", "AFG", "AGO", "AIA", "ALB", "ALD", "AND", "ARE", ...
$ adm0_a3_un <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ adm0_a3_wb <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, ...
$ continent <chr> "North America", "Asia", "Africa", "North America", "Eur...
$ region_un <chr> "Americas", "Asia", "Africa", "Americas", "Europe", "Eur...
$ subregion <chr> "Caribbean", "Southern Asia", "Middle Africa", "Caribbea...
$ region_wb <chr> "Latin America & Caribbean", "South Asia", "Sub-Saharan ...
$ name_len <dbl> 5, 11, 6, 8, 7, 5, 7, 20, 9, 7, 14, 10, 23, 22, 17, 9, 7...
$ long_len <dbl> 5, 11, 6, 8, 7, 13, 7, 20, 9, 7, 14, 10, 27, 35, 19, 9, ...
$ abbrev_len <dbl> 5, 4, 4, 4, 4, 5, 4, 6, 4, 4, 9, 4, 7, 10, 6, 4, 5, 4, 4...
$ tiny <dbl> 4, NA, NA, NA, NA, 5, 5, NA, NA, NA, 3, NA, NA, 2, 4, NA...
$ homepart <dbl> NA, 1, 1, NA, 1, NA, 1, 1, 1, 1, NA, 1, NA, NA, 1, 1, 1,...
$ geometry <MULTIPOLYGON [°]> MULTIPOLYGON (((-69.89912 1..., MULTIPOLYGO...
Here you can see the data about the countries in the world. Notice the geometry variable. This is used to create the outlines that we want.
Now we can use the geom_sf() function of the ggplot2 package to create a visual of simple feature (the geometry coordinates found in the geometry variable).
ggplot(data = world) +
geom_sf()

So now we can see that we have outlines of all the countries in the world.
We want to limit this just to the coordinates for the US. We will do this based on the coordinates we found on Wikipedia. According to this link, these are the latitude and longitude bounds of the continental US:
- top = 49.3457868 # north lat
- left = -124.7844079 # west long
- right = -66.9513812 # east long
- bottom = 24.7433195 # south lat
ggplot(data = world) +
geom_sf() +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE)
Now we just have a plot that is mostly limited to the outline of the US.
Now we will use the geom_point() function of the ggplot package to add scatter plot on top of the map. We want to show where the monitors are located based on the latitude and longitude values in the data.
ggplot(data = world) +
geom_sf() +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE)+
geom_point(data = pm, aes(x = lon, y = lat), size = 2,
shape = 23, fill = "darkred")
Nice!
Now let’s add county lines.
County graphical data is available from the maps package. The sf package which again is short for simple features creates a data frame about this graphical data so that we can work with it.
counties <-
sf::st_as_sf(maps::map("county", plot = FALSE,
fill = TRUE))
counties
Simple feature collection with 3076 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -124.6813 ymin: 25.12993 xmax: -67.00742 ymax: 49.38323
geographic CRS: WGS 84
First 10 features:
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
7 alabama,butler MULTIPOLYGON (((-86.8604 31...
8 alabama,calhoun MULTIPOLYGON (((-85.74313 3...
9 alabama,chambers MULTIPOLYGON (((-85.59416 3...
10 alabama,cherokee MULTIPOLYGON (((-85.46812 3...
Now we will use this data within the geom_sf() function to add this to our plot. We will also add a title using the ggtitle() function, as well as remove axis ticks and titles using the theme() function of the ggplot2 package.
monitors <- ggplot(data = world) +
geom_sf(data = counties, fill = NA, color = gray(.5))+
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_point(data = pm, aes(x = lon, y = lat), size = 2,
shape = 23, fill = "darkred") +
ggtitle("Monitor Locations") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
monitors

Great!
Now, let’s add a fill at the county-level for the true monitor values of air pollution.
First, we need to get the county map data that we just got and our air pollution data to have similarly formatted county names so that we can combine the datasets together.
We can see that in the county data the counties are listed after the state name and a comma. In addition they are all lower case.
Simple feature collection with 6 features and 1 field
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
geographic CRS: WGS 84
ID geom
1 alabama,autauga MULTIPOLYGON (((-86.50517 3...
2 alabama,baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama,barbour MULTIPOLYGON (((-85.42801 3...
4 alabama,bibb MULTIPOLYGON (((-87.02083 3...
5 alabama,blount MULTIPOLYGON (((-86.9578 33...
6 alabama,bullock MULTIPOLYGON (((-85.66866 3...
In contrast, our air pollution pm data shows counties as titles with the first letter as upper case.
dplyr::pull(pm, county) %>%
head()
[1] "Baldwin" "Clay" "Colbert" "DeKalb" "Etowah" "Houston"
We can use the separate() function of the tidyr package to separate the ID variable of our counties data into two variables based on the comma as a separator.
counties %<>%
tidyr::separate(ID, into = c("state", "county"), sep = ",")
head(counties)
Simple feature collection with 6 features and 2 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: -88.01778 ymin: 30.24071 xmax: -85.06131 ymax: 34.2686
geographic CRS: WGS 84
state county geom
1 alabama autauga MULTIPOLYGON (((-86.50517 3...
2 alabama baldwin MULTIPOLYGON (((-87.93757 3...
3 alabama barbour MULTIPOLYGON (((-85.42801 3...
4 alabama bibb MULTIPOLYGON (((-87.02083 3...
5 alabama blount MULTIPOLYGON (((-86.9578 33...
6 alabama bullock MULTIPOLYGON (((-85.66866 3...
Now we just need to make these names in the new county variable of the counties data to be in title format. We can use the str_to_title() function of the stringr package to do this.
counties[["county"]] <- stringr::str_to_title(counties[["county"]])
Great! Now the county information is the same for the counties and pm data.
We can use the inner_join() function of the dplyr package to join the datasets together based on the county variables in each. This function will keep all rows that are in both datasets.
map_data <-dplyr::inner_join(counties, pm, by = "county")
glimpse(map_data)
Rows: 3,926
Columns: 52
$ state.x <chr> "alabama", "alabama", "alabama", "alaba...
$ county <chr> "Baldwin", "Bibb", "Bibb", "Butler", "B...
$ id <fct> 1003.001, 13021.0007, 13021.0012, 39017...
$ value <dbl> 9.597647, 12.253134, 12.233673, 13.9180...
$ fips <fct> 1003, 13021, 13021, 39017, 39017, 13059...
$ lat <dbl> 30.49800, 32.77746, 32.80541, 39.49380,...
$ lon <dbl> -87.88141, -83.64110, -83.54352, -84.35...
$ state.y <chr> "Alabama", "Georgia", "Georgia", "Ohio"...
$ city <chr> "In a city", "In a city", "In a city", ...
$ CMAQ <dbl> 8.098836, 11.716801, 11.716801, 11.3219...
$ zcta <fct> 36532, 31206, 31020, 45044, 45015, 3060...
$ zcta_area <dbl> 190980522, 72325015, 276913325, 9874681...
$ zcta_pop <dbl> 27829, 29072, 2541, 52822, 12038, 39952...
$ imp_a500 <dbl> 0.01730104, 35.64359862, 0.28200692, 27...
$ imp_a1000 <dbl> 1.4096021, 24.4824827, 0.2973616, 28.28...
$ imp_a5000 <dbl> 3.3360118, 8.7317283, 2.4691097, 22.697...
$ imp_a10000 <dbl> 1.9879187, 9.1999720, 1.9873487, 11.901...
$ imp_a15000 <dbl> 1.4386207, 6.4619966, 3.6435089, 8.4052...
$ county_area <dbl> 4117521611, 646879637, 646879637, 12096...
$ county_pop <dbl> 182265, 155547, 155547, 368130, 368130,...
$ log_dist_to_prisec <dbl> 4.648181, 7.635438, 7.576493, 5.959728,...
$ log_pri_length_5000 <dbl> 8.517193, 10.215058, 10.659655, 9.74773...
$ log_pri_length_10000 <dbl> 9.210340, 12.116408, 11.653566, 10.7343...
$ log_pri_length_15000 <dbl> 9.630228, 12.591833, 12.313347, 11.1728...
$ log_pri_length_25000 <dbl> 11.32735, 13.12475, 13.02383, 12.14238,...
$ log_prisec_length_500 <dbl> 7.295356, 6.214608, 6.214608, 8.104926,...
$ log_prisec_length_1000 <dbl> 8.195119, 7.600902, 7.600902, 9.180109,...
$ log_prisec_length_5000 <dbl> 10.81504, 11.61283, 11.34202, 11.63677,...
$ log_prisec_length_10000 <dbl> 11.88680, 13.23991, 12.47152, 12.62117,...
$ log_prisec_length_15000 <dbl> 12.20572, 13.74532, 13.37704, 13.26170,...
$ log_prisec_length_25000 <dbl> 13.41395, 14.28483, 14.25295, 14.16745,...
$ log_nei_2008_pm25_sum_10000 <dbl> 0.3180354, 5.5380414, 0.1972941, 7.2307...
$ log_nei_2008_pm25_sum_15000 <dbl> 1.967359, 5.538041, 5.536822, 7.408732,...
$ log_nei_2008_pm25_sum_25000 <dbl> 5.067308, 5.986616, 5.986572, 7.538614,...
$ log_nei_2008_pm10_sum_10000 <dbl> 1.3558851, 5.6035407, 0.9849611, 7.2785...
$ log_nei_2008_pm10_sum_15000 <dbl> 2.2678341, 5.6035407, 5.5971561, 7.4899...
$ log_nei_2008_pm10_sum_25000 <dbl> 5.6287284, 6.0302900, 6.0347672, 7.6330...
$ popdens_county <dbl> 44.265706, 240.457407, 240.457407, 304....
$ popdens_zcta <dbl> 145.716431, 401.963277, 9.176156, 534.9...
$ nohs <dbl> 3.300, 8.700, 6.800, 1.300, 3.500, 3.80...
$ somehs <dbl> 4.900, 24.700, 17.500, 3.300, 7.700, 6....
$ hs <dbl> 25.10, 32.60, 46.60, 33.40, 33.40, 17.8...
$ somecollege <dbl> 19.7, 12.9, 18.7, 23.0, 23.2, 16.1, 18....
$ associate <dbl> 8.200, 4.800, 5.000, 8.700, 8.100, 5.10...
$ bachelor <dbl> 25.30, 8.90, 4.00, 22.20, 16.20, 25.40,...
$ grad <dbl> 13.50, 7.30, 1.30, 8.10, 7.90, 25.00, 3...
$ pov <dbl> 6.100, 38.800, 26.800, 0.900, 6.900, 12...
$ hs_orless <dbl> 33.30, 66.00, 70.90, 38.00, 44.60, 28.4...
$ urc2013 <dbl> 4, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, ...
$ urc2006 <dbl> 5, 4, 4, 2, 2, 4, 6, 2, 4, 1, 1, 1, 3, ...
$ aod <dbl> 37.36364, 36.25000, 30.45455, 48.36364,...
$ geom <MULTIPOLYGON [°]> MULTIPOLYGON (((-87.93757 ...
Nice! we can see that we have add a geom variable to the pm data.
Now we can use this to color the counties in our plot based on the value variable of our pm data, which you may recall is the actual monitor data for fine particulate air pollution at each monitor.
WE can do so using the scale_fill_gradientn() function of the ggplot2 package which creates color gradient based on a variable. In this case it is the variable that was specified as the fill in the aes function of the geom_sf() function. We specified that it would be the value variable of the pm data.
This scale_fill_gradientn() function also allows you to specify the colors, what to do about NA values (should they be a specific color or transparent) and the breaks, limits, labels and name/title on the legend for the color gradient.
truth <-ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50), expand = FALSE)+
geom_sf(data = map_data, aes(fill = value)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("True PM 2.5 levels") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
truth
Nice!
Now let’s do the same with our predicted outcome values.
Let’s grab both the testing and training predicted outcome values so that we have as much data as possible.
First we need to fit our training data with our final model to be able to get the predictions for the monitors included in the training set. We did this using the last_fit() function, but the output of this makes it difficult to grab the predicted values for the training data, and it is also difficult to get the id variables for the testing data.
Thus we will use the parsnip fit() and predict() functions of the parsnip package to do this like so:
Question Opportunity
Why do we not need pre-processed data?
Click here to reveal the answer.
Since we are using a workflow, the data will be pre-processed when it is fit as well.
RF_final_train_fit <- parsnip::fit(RF_tuned_wflow, data = train_pm)
RF_final_test_fit <- parsnip::fit(RF_tuned_wflow, data = test_pm)
values_pred_train <-
predict(RF_final_train_fit, train_pm) %>%
bind_cols(train_pm %>% select(value, fips, county, id))
values_pred_train
# A tibble: 584 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 10.0 9.60 1003 Baldwin 1003.001
2 10.9 10.8 1027 Clay 1027.0001
3 11.5 11.2 1033 Colbert 1033.1002
4 12.1 12.4 1055 Etowah 1055.001
5 10.7 10.5 1069 Houston 1069.0003
6 14.7 15.6 1073 Jefferson 1073.0023
7 12.2 12.4 1073 Jefferson 1073.1005
8 11.0 11.1 1073 Jefferson 1073.1009
9 13.8 14.6 1073 Jefferson 1073.2003
10 11.8 12.0 1073 Jefferson 1073.5002
# ... with 574 more rows
values_pred_test <-
predict(RF_final_test_fit, test_pm) %>%
bind_cols(test_pm %>% select(value, fips, county, id))
values_pred_test
# A tibble: 292 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.6 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.6 11.4 1103 Morgan 1103.0011
6 12.3 12.2 1121 Talladega 1121.0002
7 11.0 10.9 4013 Maricopa 4013.4003
8 10.5 10.6 4021 Pinal 4021.0001
9 12.1 14.1 4023 Santa Cruz 4023.0004
10 7.33 5.83 4025 Yavapai 4025.2002
# ... with 282 more rows
Now we can combine this data for the predictions for all monitors using the bind_rows() function of the dplyr package, which will essentially append the second dataset to the first.
all_pred <- bind_rows(values_pred_test, values_pred_train)
all_pred
# A tibble: 876 x 5
.pred value fips county id
<dbl> <dbl> <fct> <chr> <fct>
1 11.6 11.7 1049 DeKalb 1049.1003
2 12.6 13.1 1073 Jefferson 1073.101
3 12.3 12.2 1073 Jefferson 1073.2006
4 12.0 12.2 1089 Madison 1089.0014
5 11.6 11.4 1103 Morgan 1103.0011
6 12.3 12.2 1121 Talladega 1121.0002
7 11.0 10.9 4013 Maricopa 4013.4003
8 10.5 10.6 4021 Pinal 4021.0001
9 12.1 14.1 4023 Santa Cruz 4023.0004
10 7.33 5.83 4025 Yavapai 4025.2002
# ... with 866 more rows
Great! as we can see there are 876 values like we would expect for all of the monitors. We can use the county variable to combine this with the counties data like we did with the pm data previously so that we can use the value variable as a color scheme for our map.
map_data <- inner_join(counties, all_pred, by = "county")
pred <- ggplot(data = world) +
coord_sf(xlim = c(-125, -66), ylim = c(24.5, 50),
expand = FALSE) +
geom_sf(data = map_data, aes(fill = .pred)) +
scale_fill_gradientn(colours=topo.colors(7), na.value = "transparent",
breaks=c(0,10,20),labels=c(0,10,20),
limits=c(0,23.5), name = "PM ug/m3") +
ggtitle("Predicted PM 2.5 levels")+
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
pred

Now we will use the patchwork package to combine our last two plots. This allows us to combine plots using the + or the / . The + will place plots side by side and the / will place plots top to bottom.
Now let’s just combine the truth plot and the prediction plots together:

We can see that the predicted fine particle air pollution values in (ug/m3) are quite similar to the true values measured by the actual gravimetric monitors. We can also see that southern California has some large counties with worse pollution (as they are yellow and thus have much higher particulate matter levels).
Let’s add some text to our plot to explain it a bit more. We can do so using the plot_annotation() function of the patchwork package. The theme argument of this function takes the same theme information using the theme() function of the ggplot2 package as when creating ggplot2plots.
(truth/pred) + plot_annotation(title = "Machine Learning Methods Allow for Prediction of Air Pollution", subtitle = "A random forest model predicts true monitored levels of fine particulate matter (PM 2.5) air pollution based on\ndata about population density and other predictors reasonably well, thus suggesting that we can predict levels\nof pollution in places with poor monitoring", theme = theme(plot.title = element_text(size =12, face = "bold"), plot.subtitle = element_text(size = 8)))

LS0tDQp0aXRsZTogIk9wZW4gQ2FzZSBTdHVkaWVzOiBQcmVkaWN0aW5nIEFubnVhbCBBaXIgUG9sbHV0aW9uIg0KY3NzOiBzdHlsZS5jc3MNCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBpbmNsdWRlczoNCiAgICAgIGluX2hlYWRlcjogaGVhZGVyLmh0bWwNCiAgICBzZWxmX2NvbnRhaW5lZDogeWVzDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0aGVtZTogY29zbW8NCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQotLS0NCjxzdHlsZT4NCiNUT0Mgew0KICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9pbWcvaWNvbi1iYWhpLnBuZyIpOw0KICBiYWNrZ3JvdW5kLXNpemU6IGNvbnRhaW47DQogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50Ow0KICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Ow0KfQ0KPC9zdHlsZT4NCg0KPCEtLSBPcGVuIGFsbCBsaW5rcyBpbiBuZXcgdGFiLS0+ICANCjxiYXNlIHRhcmdldD0iX2JsYW5rIi8+IA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGhlcmUpDQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGNhY2hlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIsIG91dC53aWR0aCA9ICc5MCUnKQ0KYGBgDQoNCg0KIyMjIyB7Lm91dGxpbmUgfQ0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMCBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAibWFpbl9wbG90X21hcHMucG5nIikpDQpgYGANCg0KIyMjIw0KDQojIyMjIHsuZGlzY2xhaW1lcl9ibG9ja30NCg0KKipEaXNjbGFpbWVyKio6IFRoZSBwdXJwb3NlIG9mIHRoZSBbT3BlbiBDYXNlIFN0dWRpZXNdKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pbyl7dGFyZ2V0PSJfYmxhbmsifSBwcm9qZWN0IGlzICoqdG8gZGVtb25zdHJhdGUgdGhlIHVzZSBvZiB2YXJpb3VzIGRhdGEgc2NpZW5jZSBtZXRob2RzLCB0b29scywgYW5kIHNvZnR3YXJlIGluIHRoZSBjb250ZXh0IG9mIG1lc3N5LCByZWFsLXdvcmxkIGRhdGEqKi4gQSBnaXZlbiBjYXNlIHN0dWR5IGRvZXMgbm90IGNvdmVyIGFsbCBhc3BlY3RzIG9mIHRoZSByZXNlYXJjaCBwcm9jZXNzLCBpcyBub3QgY2xhaW1pbmcgdG8gYmUgdGhlIG1vc3QgYXBwcm9wcmlhdGUgd2F5IHRvIGFuYWx5emUgYSBnaXZlbiBkYXRhIHNldCwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBpbiB0aGUgY29udGV4dCBvZiBtYWtpbmcgcG9saWN5IGRlY2lzaW9ucyB3aXRob3V0IGV4dGVybmFsIGNvbnN1bHRhdGlvbiBmcm9tIHNjaWVudGlmaWMgZXhwZXJ0cy4gDQoNCiMjIyMNCg0KIyMjIyB7LmxpY2Vuc2VfYmxvY2t9DQoNClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9IFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4NCg0KIyMjIw0KDQojIyMjIHsucmVmZXJlbmNlX2Jsb2NrfQ0KDQpUbyBjaXRlIHRoaXMgY2FzZSBzdHVkeSBwbGVhc2UgdXNlOg0KDQpXcmlnaHQsIENhcnJpZSBhbmQgSmFnZXIsIExlYWggYW5kIFRhdWIsIE1hcmdhcmV0IGFuZCBIaWNrcywgU3RlcGhhbmllLiAoMjAyMCkuIFtodHRwczovL2dpdGh1Yi5jb20vL29wZW5jYXNlc3R1ZGllcy9vY3MtYnAtYWlyLXBvbGx1dGlvbl0oaHR0cHM6Ly9naXRodWIuY29tLy9vcGVuY2FzZXN0dWRpZXMvb2NzLWJwLWFpci1wb2xsdXRpb24vKS4gUHJlZGljdGluZyBBbm51YWwgQWlyIFBvbGx1dGlvbiAoVmVyc2lvbiB2MS4wLjApLg0KDQojIyMjDQoNClRvIGFjY2VzcyB0aGUgR2l0SHViIFJlcG9zaXRvcnkgZm9yIHRoaXMgY2FzZSBzdHVkeSBzZWUgaGVyZTogaHR0cHM6Ly9naXRodWIuY29tL29wZW5jYXNlc3R1ZGllcy9vY3MtYnAtYWlyLXBvbGx1dGlvbi4NCg0KVGhpcyBjYXNlIHN0dWR5IGlzIHBhcnQgb2YgYSBzZXJpZXMgb2YgcHVibGljIGhlYWx0aCBjYXNlIHN0dWRpZXMgZm9yIHRoZSBbQmxvb21iZXJnIEFtZXJpY2FuIEhlYWx0aCAgSW5pdGlhdGl2ZV0oaHR0cHM6Ly9hbWVyaWNhbmhlYWx0aC5qaHUuZWR1L29wZW4tY2FzZS1zdHVkaWVzKS4NCg0KIyAqKk1vdGl2YXRpb24qKg0KKioqDQpBIHZhcmlldHkgb2YgZGlmZmVyZW50IHNvdXJjZXMgY29udHJpYnV0ZSBkaWZmZXJlbnQgdHlwZXMgb2YgcG9sbHV0YW50cyB0byB3aGF0IHdlIGNhbGwgYWlyIHBvbGx1dGlvbi4gDQoNClNvbWUgc291cmNlcyBhcmUgbmF0dXJhbCB3aGlsZSBvdGhlcnMgYXJlIGFudGhyb3BvZ2VuaWMgKGh1bWFuIGRlcml2ZWQpOg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCjxpbWcgd2lkdGg9IjYwMCIgc3JjPSJodHRwczovL3d3dy5ucHMuZ292L3N1YmplY3RzL2Fpci9pbWFnZXMvU291cmNlc19HcmFwaGljX0h1Z2UuanBnP21heHdpZHRoPTEyMDAmbWF4aGVpZ2h0PTEyMDAmYXV0b3JvdGF0ZT1mYWxzZSI+DQo8L3A+DQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS91cmw/c2E9aSZ1cmw9aHR0cHMlM0ElMkYlMkZ3d3cubnBzLmdvdiUyRnN1YmplY3RzJTJGYWlyJTJGc291cmNlcy5odG0mcHNpZz1BT3ZWYXcydjdBVnhTRjhaU0FQRWhOdWRWdGJOJnVzdD0xNTg1NzcwOTY2MjE3MDAwJnNvdXJjZT1pbWFnZXMmY2Q9dmZlJnZlZD0wQ0FJUWpSeHFGd29UQ1BETjY2cV94ZWdDRlFBQUFBQWRBQUFBQUJBRCl7dGFyZ2V0PSJfYmxhbmsifQ0KDQojIyMgTWFqb3IgdHlwZXMgb2YgYWlyIHBvbGx1dGFudHMNCg0KMSkgKipHYXNlb3VzKiogLSBDYXJib24gTW9ub3hpZGUgKENPKSwgT3pvbmUgKE9+M34pLCBOaXRyb2dlbiBPeGlkZXMoTk8sIE5PfjJ+KSwgU3VscGhlciBEaW94aWRlIChTT34yfikNCjIpICoqUGFydGljdWxhdGUqKiAtIHNtYWxsIGxpcXVpZHMgYW5kIHNvbGlkcyBzdXNwZW5kZWQgaW4gdGhlIGFpciAoaW5jbHVkZXMgbGVhZC0gY2FuIGluY2x1ZGUgY2VydGFpbiB0eXBlcyBvZiBkdXN0KQ0KMykgKipEdXN0KiogLSBzbWFsbCBzb2xpZHMgKGxhcmdlciB0aGFuIHBhcnRpY3VsYXRlcykgdGhhdCBjYW4gYmUgc3VzcGVuZGVkIGluIHRoZSBhaXIgZm9yIHNvbWUgdGltZSBidXQgZXZlbnR1YWxseSBzZXR0bGUNCjQpICoqQmlvbG9naWNhbCoqIC0gcG9sbGVuLCBiYWN0ZXJpYSwgdmlydXNlcywgbW9sZCBzcG9yZXMNCg0KU2VlIFtoZXJlXShodHRwOi8vd3d3LnJlZGxvZ2Vudi5jb20vd29ya2VyLXNhZmV0eS9wYXJ0LTEtZHVzdC1hbmQtcGFydGljdWxhdGUtbWF0dGVyKSBmb3IgbW9yZSBkZXRhaWwgb24gdGhlIHR5cGVzIG9mIHBvbGx1dGFudHMgaW4gdGhlIGFpci4NCg0KDQojIyMgUGFydGljdWxhdGUgcG9sbHV0aW9uIA0KDQpBaXIgcG9sbHV0aW9uIHBhcnRpY3VsYXRlcyBhcmUgZ2VuZXJhbGx5IGRlc2NyaWJlZCBieSB0aGVpciAqKnNpemUqKi4NCg0KVGhlcmUgYXJlIDMgbWFqb3IgY2F0ZWdvcmllczoNCg0KMSkgKipMYXJnZSBDb2Fyc2UqKiBQYXJ0aWN1bGF0ZSBNYXR0ZXIgLSBoYXMgZGlhbWV0ZXIgb2YgPjEwIG1pY3JvbWV0ZXJzICgxMCDCtW0pIA0KDQoyKSAqKkNvYXJzZSoqIFBhcnRpY3VsYXRlIE1hdHRlciAoY2FsbGVkICoqUE1+MTAtMi41fioqKSAtIGhhcyBkaWFtZXRlciBvZiBiZXR3ZWVuIDIuNSDCtW0gYW5kIDEwIMK1bQ0KDQozKSAqKkZpbmUqKiBQYXJ0aWN1bGF0ZSBNYXR0ZXIgKGNhbGxlZCAqKlBNfjIuNX4qKikgLSBoYXMgZGlhbWV0ZXIgb2YgPCAyLjUgwrVtIA0KDQoqKlBNfjEwfioqIGluY2x1ZGVzIGFueSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgPDEwIMK1bSAoYm90aCBjb2Fyc2UgYW5kIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyKQ0KDQpIZXJlIHlvdSBjYW4gc2VlIGhvdyB0aGVzZSBzaXplcyBjb21wYXJlIHdpdGggYSBodW1hbiBoYWlyOg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9ICI2MDAgcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInBtMi41X3NjYWxlX2dyYXBoaWMtY29sb3JfMi5qcGciKSkNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmVwYS5nb3YvcG0tcG9sbHV0aW9uL3BhcnRpY3VsYXRlLW1hdHRlci1wbS1iYXNpY3Mpe3RhcmdldD0iX2JsYW5rIn0NCg0KPCEtLSA8cCBhbGlnbj0iY2VudGVyIj4gLS0+DQo8IS0tICAgPGltZyB3aWR0aD0iNTAwIiBzcmM9Imh0dHBzOi8vd3d3LnNlbnNpcmlvbi5jb20vaW1hZ2VzL3NlbnNpcmlvbi1zcGVjaWFsaXN0LWFydGljbGUtZmlndXJlLTEtY2RkNzAuanBnIj4gLS0+DQo8IS0tIDwvcD4gLS0+DQoNCg0KPHU+VGhlIGZvbGxvd2luZyBwbG90IGFuZCB0YWJsZSBzaG93IHRoZSByZWxhdGl2ZSBzaXplcyBvZiB0aGVzZSBkaWZmZXJlbnQgcG9sbHV0YW50cyBpbiBtaWNyb21ldGVycyAowrVtKTo8L3U+DQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjgwMCBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicGFydGljdWxhdGUtc2l6ZS1jaGFydC5wbmciKSkNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhcnRpY3VsYXRlcyl7dGFyZ2V0PSJfYmxhbmsifQ0KDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjgwMCBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicGFydGljdWxhdGVfdHlwZXMuanBnIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpe3RhcmdldD0iX2JsYW5rIn0NCg0KDQo8dT5UaGlzIHRhYmxlIHNob3dzIGhvdyBkZWVwbHkgc29tZSBvZiB0aGUgc21hbGxlciBmaW5lIHBhcnRpY2xlcyBjYW4gcGVuZXRyYXRlIHdpdGhpbiB0aGUgaHVtYW4gYm9keTo8L3U+DQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0gIjgwMCBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAic2l6ZXMuanBnIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcHViaC4yMDIwLjAwMDE0L2Z1bGwpe3RhcmdldD0iX2JsYW5rIn0NCg0KDQojIyMgTmVnYXRpdmUgaW1wYWN0IG9mIHBhcnRpY3VsYXRlIGV4cG9zdXJlIG9uIGhlYWx0aCANCg0KRXhwb3N1cmUgdG8gYWlyIHBvbGx1dGlvbiBpcyBhc3NvY2lhdGVkIHdpdGggaGlnaGVyIHJhdGVzIG9mIFttb3J0YWxpdHldKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzU3ODMxODYvKXt0YXJnZXQ9Il9ibGFuayJ9IGluIG9sZGVyIGFkdWx0cyBhbmQgaXMga25vd24gdG8gYmUgYSByaXNrIGZhY3RvciBmb3IgbWFueSBkaXNlYXNlcyBhbmQgY29uZGl0aW9ucyBpbmNsdWRpbmcgYnV0IG5vdCBsaW1pdGVkIHRvOg0KDQoxKSBbQXN0aG1hXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8yOTI0MzkzNyl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKCoqUE1+Mi41fioqKSB3YXMgZm91bmQgdG8gYmUgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciByYXRlcyBvZiBhc3RobWEgaW4gY2hpbGRyZW4NCjIpIFtJbmZsYW1tYXRpb24gaW4gdHlwZSAxIGRpYWJldGVzXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8zMTQxOTc2NSl7dGFyZ2V0PSJfYmxhbmsifSAtIGZpbmUgcGFydGljbGUgZXhwb3N1cmUgKCoqUE1+Mi41fioqKSBmcm9tIHRyYWZmaWMtcmVsYXRlZCBhaXIgcG9sbHV0aW9uIHdhcyBhc3NvY2lhdGVkIHdpdGggaW5jcmVhc2VkIG1lYXN1cmVzIG9mIGluZmxhbW1hdG9yeSBtYXJrZXJzIGluIHlvdXRocyB3aXRoIFR5cGUgMSBkaWFiZXRlcw0KMykgW0x1bmcgZnVuY3Rpb24gYW5kIGVtcGh5c2VtYV0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzE0MDgxMzUpe3RhcmdldD0iX2JsYW5rIn0gLSBoaWdoZXIgY29uY2VudHJhdGlvbnMgb2Ygb3pvbmUgKE9+M34pLCBuaXRyb2dlbiBveGlkZXMgKE5Pfnh+KSwgYmxhY2sgY2FyYm9uLCBhbmQgZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAqKlBNfjIuNX4qKiAsIGF0IHN0dWR5IGJhc2VsaW5lIHdlcmUgc2lnbmlmaWNhbnRseSBhc3NvY2lhdGVkIHdpdGggZ3JlYXRlciBpbmNyZWFzZXMgaW4gcGVyY2VudCBlbXBoeXNlbWEgcGVyIDEwIHllYXJzIA0KNCkgW0xvdyBiaXJ0aHdlaWdodF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wdWJtZWQvMzEzODY2NDMpe3RhcmdldD0iX2JsYW5rIn0gLSBmaW5lIHBhcnRpY2xlIGV4cG9zdXJlKCoqUE1+Mi41fioqKSB3YXMgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIGJpcnRoIHdlaWdodCBpbiBmdWxsLXRlcm0gbGl2ZSBiaXJ0aHMNCjUpIFtWaXJhbCBJbmZlY3Rpb25dKGh0dHBzOi8vd3d3LnRhbmRmb25saW5lLmNvbS9kb2kvZnVsbC8xMC4xMDgwLzA4OTU4MzcwNzAxNjY1NDM0KXt0YXJnZXQ9Il9ibGFuayJ9IC0gaGlnaGVyIHJhdGVzIG9mIGluZmVjdGlvbiBhbmQgaW5jcmVhc2VkIHNldmVyaXR5IG9mIGluZmVjdGlvbiBhcmUgYXNzb2NpYXRlZCB3aXRoIGhpZ2hlciBleHBvc3VyZXMgdG8gcG9sbHV0aW9uIGxldmVscyBpbmNsdWRpbmcgZmluZSBwYXJ0aWNsZSBleHBvc3VyZSAoKipQTX4yLjV+KiopDQoNClNlZSB0aGlzIFtyZXZpZXcgYXJ0aWNsZV0oaHR0cHM6Ly93d3cuZnJvbnRpZXJzaW4ub3JnL2FydGljbGVzLzEwLjMzODkvZnB1YmguMjAyMC4wMDAxNC9mdWxsKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHNvdXJjZXMgb2YgYWlyIHBvbGx1dGlvbiBhbmQgdGhlIGluZmx1ZW5jZSBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aC4NCg0KIyMjIFNwYXJzZSBtb25pdG9yaW5nIGlzIHByb2JsZW1hdGljIGZvciBQdWJsaWMgSGVhbHRoDQoNCkhpc3RvcmljYWxseSwgZXBpZGVtaW9sb2dpY2FsIHN0dWRpZXMgd291bGQgYXNzZXNzIHRoZSBpbmZsdWVuY2Ugb2YgYWlyIHBvbGx1dGlvbiBvbiBoZWFsdGggb3V0Y29tZXMgYnkgcmVseWluZyBvbiBhIG51bWJlciBvZiBtb25pdG9ycyBsb2NhdGVkIGFyb3VuZCB0aGUgY291bnRyeS4gDQoNCkhvd2V2ZXIsIGFzIGNhbiBiZSBzZWVuIGluIHRoZSBmb2xsb3dpbmcgZmlndXJlLCB0aGVzZSBtb25pdG9ycyBhcmUgcmVsYXRpdmVseSBzcGFyc2UgaW4gY2VydGFpbiByZWdpb25zIG9mIHRoZSBjb3VudHJ5IGFuZCBhcmUgbm90IG5lY2Vzc2FyaWx5IGxvY2F0ZWQgbmVhciBwb2xsdXRpb24gc291cmNlcy4gV2Ugd2lsbCBzZWUgbGF0ZXIgd2hlbiB3ZSBldmFsdWF0ZSB0aGUgZGF0YSwgdGhhdCBldmVuIGluIGNlcnRhaW4gcmVsYXRpdmVseSBsYXJnZSBjaXRpZXMgdGhlcmUgaXMgb25seSAgb25lIG1vbml0b3IhDQoNCkZ1cnRoZXJtb3JlLCBkcmFtYXRpYyBkaWZmZXJlbmNlcyBpbiBwb2xsdXRpb24gcmF0ZXMgY2FuIGJlIHNlZW4gZXZlbiB3aXRoaW4gdGhlIHNhbWUgY2l0eS4gSW4gZmFjdCwgdGhlIHRlcm0gbWljcm8tZW52aXJvbm1lbnRzIGRlc2NyaWJlcyBlbnZpcm9ubWVudCB3aXRoaW4gY2l0aWVzIG9yIGNvdW50aWVzIHdoaWNoIG1heSB2YXJ5IGdyZWF0bHkgZnJvbSBvbmUgYmxvY2sgdG8gYW5vdGhlci4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJtYXBfb2ZfbW9uaXRvcnMuanBnIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifQ0KDQpUaGlzIGxhY2sgb2YgZ3JhbnVsYXJpdHkgaW4gYWlyIHBvbGx1dGlvbiBtb25pdG9yaW5nIGhhcyBoaW5kZXJlZCBvdXIgYWJpbGl0eSB0byBkaXNjZXJuIHRoZSBmdWxsIGltcGFjdCBvZiBhaXIgcG9sbHV0aW9uIG9uIGhlYWx0aCBhbmQgdG8gaWRlbnRpZnkgYXQtcmlzayBsb2NhdGlvbnMuIA0KDQoNCiMjIyBNYWNoaW5lIGxlYXJuaW5nIG9mZmVycyBhIHNvbHV0aW9uDQoNCkFuIFthcnRpY2xlXShodHRwczovL2Voam91cm5hbC5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2LzE0NzYtMDY5WC0xMy02Myl7dGFyZ2V0PSJfYmxhbmsifSBwdWJsaXNoZWQgaW4gdGhlICpFbnZpcm9ubWVudGFsIEhlYWx0aCogam91cm5hbCBkZWFsdCB3aXRoIHRoaXMgaXNzdWUgYnkgdXNpbmcgZGF0YSwgaW5jbHVkaW5nIHBvcHVsYXRpb24gZGVuc2l0eSwgcm9hZCBkZW5zaXR5LCBhbW9uZyBvdGhlciBmZWF0dXJlcywgdG8gbW9kZWwgb3IgcHJlZGljdCBhaXIgcG9sbHV0aW9uIGxldmVscyBhdCBhIG1vcmUgbG9jYWxpemVkIHNjYWxlIHVzaW5nIG1hY2hpbmUgbGVhcm5pbmcgKE1MKSBtZXRob2RzLiANCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSAiODAwIHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJ0aGVwYXBlci5wbmciKSkNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vZWhqb3VybmFsLmJpb21lZGNlbnRyYWwuY29tL2FydGljbGVzLzEwLjExODYvMTQ3Ni0wNjlYLTEzLTYzKXt0YXJnZXQ9Il9ibGFuayJ9DQoNCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9DQpZYW5vc2t5LCBKLiBELiBldCBhbC4gU3BhdGlvLXRlbXBvcmFsIG1vZGVsaW5nIG9mIHBhcnRpY3VsYXRlIGFpciBwb2xsdXRpb24gaW4gdGhlIGNvbnRlcm1pbm91cyBVbml0ZWQgU3RhdGVzIHVzaW5nIGdlb2dyYXBoaWMgYW5kIG1ldGVvcm9sb2dpY2FsIHByZWRpY3RvcnMuICpFbnZpcm9uIEhlYWx0aCogMTMsIDYzICgyMDE0KS4NCg0KIyMjIw0KDQpUaGUgYXV0aG9ycyBvZiB0aGlzIGFydGljbGUgc3RhdGUgdGhhdDoNCg0KPiAiRXhwb3N1cmUgdG8gYXRtb3NwaGVyaWMgcGFydGljdWxhdGUgbWF0dGVyIChQTSkgcmVtYWlucyBhbiBpbXBvcnRhbnQgcHVibGljIGhlYWx0aCBjb25jZXJuLCBhbHRob3VnaCBpdCByZW1haW5zIGRpZmZpY3VsdCB0byBxdWFudGlmeSBhY2N1cmF0ZWx5IGFjcm9zcyBsYXJnZSBnZW9ncmFwaGljIGFyZWFzIHdpdGggc3VmZmljaWVudGx5IGhpZ2ggc3BhdGlhbCByZXNvbHV0aW9uLiBSZWNlbnQgZXBpZGVtaW9sb2dpYyBhbmFseXNlcyBoYXZlIGRlbW9uc3RyYXRlZCB0aGUgaW1wb3J0YW5jZSBvZiBzcGF0aWFsbHktIGFuZCB0ZW1wb3JhbGx5LXJlc29sdmVkIGV4cG9zdXJlIGVzdGltYXRlcywgd2hpY2ggc2hvdyBsYXJnZXIgUE0tbWVkaWF0ZWQgaGVhbHRoIGVmZmVjdHMgYXMgY29tcGFyZWQgdG8gbmVhcmVzdCBtb25pdG9yIG9yIGNvdW50eS1zcGVjaWZpYyBhbWJpZW50IGNvbmNlbnRyYXRpb25zLiIgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9laGpvdXJuYWwuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni8xNDc2LTA2OVgtMTMtNjMpe3RhcmdldD0iX2JsYW5rIn0NCg0KVGhlIGFydGljbGUgYWJvdmUgZGVtb25zdHJhdGVzIHRoYXQgbWFjaGluZSBsZWFybmluZyBtZXRob2RzIGNhbiBiZSB1c2VkIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBsZXZlbHMgd2hlbiB0cmFkaXRpb25hbCBtb25pdG9yaW5nIHN5c3RlbXMgYXJlIG5vdCBhdmFpbGFibGUgaW4gYSBwYXJ0aWN1bGFyIGFyZWEgb3Igd2hlbiB0aGVyZSBpcyBub3QgZW5vdWdoIHNwYXRpYWwgZ3JhbnVsYXJpdHkgd2l0aCBjdXJyZW50IG1vbml0b3Jpbmcgc3lzdGVtcy4gDQpXZSB3aWxsIHVzZSBzaW1pbGFyIG1ldGhvZHMgdG8gcHJlZGljdCBhbm51YWwgYWlyIHBvbGx1dGlvbiBsZXZlbHMgc3BhdGlhbGx5IHdpdGhpbiB0aGUgVVMuDQoNCg0KIyAqKk1haW4gUXVlc3Rpb24qKg0KKioqDQoNCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQ0KPGI+PHU+IE91ciBtYWluIHF1ZXN0aW9uOiA8L3U+PC9iPg0KDQoxKSBDYW4gd2UgcHJlZGljdCBhbm51YWwgYXZlcmFnZSBhaXIgcG9sbHV0aW9uIGNvbmNlbnRyYXRpb25zIGF0IHRoZSBncmFudWxhcml0eSBvZiB6aXAgY29kZSByZWdpb25hbCBsZXZlbHMgdXNpbmcgcHJlZGljdG9ycyBzdWNoIGFzIGRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5LCB1cmJhbml6YXRpb24sIHJvYWQgZGVuc2l0eSwgYXMgd2VsbCBhcywgc2F0ZWxsaXRlIHBvbGx1dGlvbiBkYXRhIGFuZCBjaGVtaWNhbCBtb2RlbGluZyBkYXRhPw0KDQojIyMjDQoNCiMgKipMZWFybmluZyBPYmplY3RpdmVzKioNCioqKg0KDQpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgd2FsayB5b3UgdGhyb3VnaCBpbXBvcnRpbmcgZGF0YSBmcm9tIENTViBmaWxlcyBhbmQgcGVyZm9ybWluZyBtYWNoaW5lIGxlYXJuaW5nIG1ldGhvZHMgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSBvZiBpbnRlcmVzdCAoaW4gdGhpcyBjYXNlIGFubnVhbCBmaW5lIHBhcnRpY2xlIGFpciBwb2xsdXRpb24gZXN0aW1hdGVzKS4gDQoNCldlIHdpbGwgZXNwZWNpYWxseSBmb2N1cyBvbiB1c2luZyBwYWNrYWdlcyBhbmQgZnVuY3Rpb25zIGZyb20gdGhlIFtgdGlkeXZlcnNlYF0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0sIGFuZCBtb3JlIHNwZWNpZmljYWxseSB0aGUgW2B0aWR5bW9kZWxzYF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3RpZHltb2RlbHMvdGlkeW1vZGVscy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gcGFja2FnZS9lY29zeXN0ZW0gcHJpbWFyaWx5IGRldmVsb3BlZCBhbmQgbWFpbnRhaW5lZCBieSBbTWF4IEt1aG5dKGh0dHBzOi8vcmVzb3VyY2VzLnJzdHVkaW8uY29tL2F1dGhvcnMvbWF4LWt1aG4pe3RhcmdldD0iX2JsYW5rIn0gYW5kIFtEYXZpcyBWYXVnaGFuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL2RhdmlzLXZhdWdoYW4pe3RhcmdldD0iX2JsYW5rIn0uIA0KVGhpcyBwYWNrYWdlIGxvYWRzIG1vcmUgbW9kZWxpbmcgcmVsYXRlZCBwYWNrYWdlcyBsaWtlIGByc2FtcGxlYCwgYHJlY2lwZXNgLCBgcGFyc25pcGAsIGB5YXJkc3RpY2tgLCBgd29ya2Zsb3dzYCwgYW5kIGB0dW5lYCBwYWNrYWdlcy4gDQoNClRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gDQpXaGlsZSBzb21lIHN0dWRlbnRzIG1heSBiZSBmYW1pbGlhciB3aXRoIHByZXZpb3VzIFIgcHJvZ3JhbW1pbmcgcGFja2FnZXMsIHRoZXNlIHBhY2thZ2VzIG1ha2UgZGF0YSBzY2llbmNlIGluIFIgZXNwZWNpYWxseSBsZWdpYmxlIGFuZCBpbnR1aXRpdmUuDQoNCg0KYGBge3IsIG91dC53aWR0aCA9ICIyMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9DQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3RpZHl2ZXJzZS50aWR5dmVyc2Uub3JnL2xvZ28ucG5nIikNCmBgYA0KDQpUaGUgc2tpbGxzLCBtZXRob2RzLCBhbmQgY29uY2VwdHMgdGhhdCBzdHVkZW50cyB3aWxsIGJlIGZhbWlsaWFyIHdpdGggYnkgdGhlIGVuZCBvZiB0aGlzIGNhc2Ugc3R1ZHkgYXJlOg0KDQoNCjx1PioqRGF0YSBTY2llbmNlIExlYXJuaW5nIE9iamVjdGl2ZXM6Kio8L3U+IA0KICANCjEuIEZhbWlsaWFyaXR5IHdpdGggdGhlIHRpZHltb2RlbHMgZWNvc3lzdGVtDQoyLiBBYmlsaXR5IHRvIGV2YWx1YXRlIGNvcnJlbGF0aW9uIGFtb25nIHByZWRpY3RvciB2YXJpYWJsZXMgKGBjb3JycGxvdGAgYW5kIGBHR2FsbHlgKQ0KMy4gQWJpbGl0eSB0byBpbXBsZW1lbnQgdGlkeW1vZGVscyBwYWNrYWdlcyBzdWNoIGFzIGByc2FtcGxlYCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIHNldHMgYXMgd2VsbCBhcyBjcm9zcyB2YWxpZGF0aW9uIHNldHMuDQo0LiBBYmlsaXR5IHRvIHVzZSB0aGUgYHJlY2lwZXNgLCBgcGFyc25pcGAsIGFuZCBgd29ya2Zsb3dzYCB0byB0cmFpbiBhbmQgdGVzdCBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGFuZCByYW5kb20gZm9yZXN0IG1vZGVsDQo1LiBEZW1vbnN0cmF0ZSBob3cgdG8gdmlzdWFsaXplIGdlby1zcGF0aWFsIGRhdGEgdXNpbmcgYGdncGxvdDJgDQoNCjx1PioqU3RhdGlzdGljYWwgTGVhcm5pbmcgT2JqZWN0aXZlczoqKjwvdT4gIA0KICANCjEuIEJhc2ljIHVuZGVyc3RhbmRpbmcgdGhlIHV0aWxpdHkgb2YgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiBhbmQgY2xhc3NpZmljYXRpb24NCjIuIFVuZGVyc3RhbmRpbmcgb2YgdGhlIG5lZWQgZm9yIHRyYWluaW5nIGFuZCB0ZXN0IHNldHMNCjMuIFVuZGVyc3RhbmRpbmcgb2YgdGhlIHV0aWxpdHkgb2YgY3Jvc3MgdmFsaWRhdGlvbg0KNC4gVW5kZXJzdGFuZGluZyBvZiByYW5kb20gZm9yZXN0DQo1LiBIb3cgdG8gaW50ZXJwcmV0IHJvb3QgbWVhbiBzcXVhcmVkIGVycm9yIChybXNlKSB0byBhc3Nlc3MgcGVyZm9ybWFuY2UgZm9yIHByZWRpY3Rpb24NCg0KDQoNCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwcHgiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9DQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3Bicy50d2ltZy5jb20vbWVkaWEvRGtCRnBTc1c0QUl5eUlOLnBuZyIpDQpgYGANCg0KDQpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOg0KDQpgYGB7cn0NCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShza2ltcikNCmxpYnJhcnkoc3VtbWFyeXRvb2xzKQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeSh0aWR5bW9kZWxzKQ0KbGlicmFyeSh3b3JrZmxvd3MpDQpsaWJyYXJ5KHZpcCkNCmxpYnJhcnkodHVuZSkNCmxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KbGlicmFyeShkb1BhcmFsbGVsKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkobHdnZW9tKQ0KbGlicmFyeShzZikNCmxpYnJhcnkobWFwcykNCmxpYnJhcnkocm5hdHVyYWxlYXJ0aCkNCmxpYnJhcnkocmdlb3MpDQpsaWJyYXJ5KHBhdGNod29yaykNCmBgYA0KDQoNCiA8dT4qKlBhY2thZ2VzIHVzZWQgaW4gdGhpcyBjYXNlIHN0dWR5OioqIDwvdT4NCg0KUGFja2FnZSAgIHwgVXNlIGluIHRoaXMgY2FzZSBzdHVkeSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0NCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhDQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCBDU1YgZmlsZXMNCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gdmlldy9hcnJhbmdlL2ZpbHRlci9zZWxlY3QvY29tcGFyZSBzcGVjaWZpYyBzdWJzZXRzIG9mIGRhdGEgDQpbc2tpbXJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9za2ltci9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBnZXQgYW4gb3ZlcnZpZXcgb2YgZGF0YQ0KW3N1bW1hcnl0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhIGluIGEgZGlmZmVyZW50IHN0eWxlDQpbbWFncml0dHJdKGh0dHBzOi8vbWFncml0dHIudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byB1c2UgdGhlIGAlPD4lYCBwaXBwaW5nIG9wZXJhdG9yIA0KW2NvcnJwbG90XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY29ycnBsb3QvdmlnbmV0dGVzL2NvcnJwbG90LWludHJvLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBtYWtlIGxhcmdlIGNvcnJlbGF0aW9uIHBsb3RzDQpbR0dhbGx5XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvR0dhbGx5L0dHYWxseS5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBtYWtlIHNtYWxsZXIgY29ycmVsYXRpb24gcGxvdHMgIA0KW3RpZHltb2RlbHNdKGh0dHBzOi8vd3d3LnRpZHltb2RlbHMub3JnKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gbG9hZCBpbiBhIHNldCBvZiBwYWNrYWdlcyAoYnJvb20sIGRpYWxzLCBpbmZlciwgcGFyc25pcCwgcHVycnIsIHJlY2lwZXMsIHJzYW1wbGUsIHRpYmJsZSwgeWFyZHN0aWNrKQ0KW3JzYW1wbGVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcnNhbXBsZS9hcnRpY2xlcy9CYXNpY3MuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgdG8gc3BsaXQgdGhlIGRhdGEgaW50byB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXRzOyB0byBzcGxpdCB0aGUgdHJhaW5pbmcgc2V0IGZvciBjcm9zcy12YWxpZGF0aW9uICANCltyZWNpcGVzXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBwcmUtcHJvY2VzcyBkYXRhIGZvciBtb2RlbGluZyBpbiBhIHRpZHkgYW5kIHJlcHJvZHVjaWJsZSB3YXkgYW5kIHRvIGV4dHJhY3QgcHJlLXByb2Nlc3NlZCBkYXRhIChtYWpvciBmdW5jdGlvbnMgYXJlIGByZWNpcGUoKWAsIGBwcmVwKClgIGFuZCB2YXJpb3VzIHRyYW5zZm9ybWF0aW9uIGBzdGVwXyooKWAgZnVuY3Rpb25zLCBhcyB3ZWxsIGFzIGBiYWtlYCB3aGljaCBleHRyYWN0cyBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKHVzZWQgdG8gcmVxdWlyZSBganVpY2UoKWApIGFuZCBhcHBsaWVzIHJlY2lwZSBwcmVwcm9jZXNzaW5nIHN0ZXBzIHRvIHRlc3RpbmcgZGF0YSkuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gIGZvciBtb3JlIGluZm8uDQpbcGFyc25pcF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9wYXJzbmlwLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgYW4gaW50ZXJmYWNlIHRvIGNyZWF0ZSBtb2RlbHMgKG1ham9yIGZ1bmN0aW9ucyBhcmUgYGZpdCgpYCwgYHNldF9lbmdpbmUoKWApDQpbeWFyZHN0aWNrXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3lhcmRzdGljay8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBtb2RlbHMNClticm9vbV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTgvMDcvYnJvb20tMC01LTAvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IHRpZHkgb3V0cHV0IGZvciBvdXIgbW9kZWwgZml0IGFuZCBwZXJmb3JtYW5jZQ0KW2dncGxvdDJdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1ha2UgdmlzdWFsaXphdGlvbnMgd2l0aCBtdWx0aXBsZSBsYXllcnMNCltkaWFsc10oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy9ibG9nLzIwMTkvMTAvZGlhbHMtMC0wLTMvKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gc3BlY2lmeSBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nDQpbdHVuZV0oaHR0cHM6Ly90dW5lLnRpZHltb2RlbHMub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHBlcmZvcm0gY3Jvc3MgdmFsaWRhdGlvbiwgdHVuZSBoeXBlci1wYXJhbWV0ZXJzLCBhbmQgZ2V0IHBlcmZvcm1hbmNlIG1ldHJpY3MNClt3b3JrZmxvd3NdKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy93b3JrZmxvd3MvdmVyc2lvbnMvMC4xLjEpe3RhcmdldD0iX2JsYW5rIn18IHRvIGNyZWF0ZSBtb2RlbGluZyB3b3JrZmxvdyB0byBzdHJlYW1saW5lIHRoZSBtb2RlbGluZyBwcm9jZXNzDQpbdmlwXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdmlwL3ZpcC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjcmVhdGUgdmFyaWFibGUgaW1wb3J0YW5jZSBwbG90cw0KW3JhbmRvbUZvcmVzdF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JhbmRvbUZvcmVzdC9yYW5kb21Gb3Jlc3QucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gcGVyZm9ybSB0aGUgcmFuZG9tIGZvcmVzdCBhbmFseXNpcw0KW2RvUGFyYWxsZWxdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9kb1BhcmFsbGVsL2RvUGFyYWxsZWwucGRmKSB8IHRvIGZpdCBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgaW4gcGFyYWxsZWwgDQpbc3RyaW5ncl0oaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvc3RyaW5nci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB0aGUgbWFwIGRhdGENClt0aWR5cl0oaHR0cHM6Ly90aWR5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gc2VwYXJhdGUgZGF0YSB3aXRoaW4gYSBjb2x1bW4gaW50byBtdWx0aXBsZSBjb2x1bW5zDQpbcm5hdHVyYWxlYXJ0aF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JuYXR1cmFsZWFydGgvUkVBRE1FLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgdGhlIGdlb21ldHJ5IGRhdGEgZm9yIHRoZSBlYXJ0aCB0byBwbG90IHRoZSBVUw0KW21hcHNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYXBzL21hcHMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gZ2V0IG1hcCBkYXRhYmFzZSBkYXRhIGFib3V0IGNvdW50aWVzIHRvIGRyYXcgdGhlbSBvbiBvdXIgVVMgbWFwDQpbc2ZdKGh0dHBzOi8vci1zcGF0aWFsLmdpdGh1Yi5pby9zZi8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBjb252ZXJ0IHRoZSBtYXAgZGF0YSBpbnRvIGEgZGF0YSBmcmFtZQ0KW2x3Z2VvbV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2x3Z2VvbS9sd2dlb20ucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gdXNlIHRoZSBgc2ZgIGZ1bmN0aW9uIHRvIGNvbnZlcnQgbWFwIGdlb2dyYXBoaWNhbCBkYXRhDQpbcmdlb3NdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZ2Vvcy9yZ2Vvcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byB1c2UgZ2VvbWV0cnkgZGF0YQ0KW3BhdGNod29ya10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BhdGNod29yay9wYXRjaHdvcmsucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gYWxsb3cgcGxvdHMgdG8gYmUgY29tYmluZWQNCl9fXw0KDQoNClRoZSBmaXJzdCB0aW1lIHdlIHVzZSBhIGZ1bmN0aW9uLCB3ZSB3aWxsIHVzZSB0aGUgYDo6YCB0byBpbmRpY2F0ZSB3aGljaCBwYWNrYWdlIHdlIGFyZSB1c2luZy4gDQpVbmxlc3Mgd2UgaGF2ZSBvdmVybGFwcGluZyBmdW5jdGlvbiBuYW1lcywgdGhpcyBpcyBub3QgbmVjZXNzYXJ5LCBidXQgd2Ugd2lsbCBpbmNsdWRlIGl0IGhlcmUgdG8gYmUgaW5mb3JtYXRpdmUgYWJvdXQgd2hlcmUgdGhlIGZ1bmN0aW9ucyB3ZSB3aWxsIHVzZSBjb21lIGZyb20uDQoNCg0KIyAqKkNvbnRleHQqKg0KKioqDQoNClRoZSBbU3RhdGUgb2YgR2xvYmFsIEFpcl0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9IGlzIGEgcmVwb3J0IHJlbGVhc2VkIGV2ZXJ5IHllYXIgdG8gY29tbXVuaWNhdGUgdGhlIGltcGFjdCBvZiBhaXIgcG9sbHV0aW9uIG9uIHB1YmxpYyBoZWFsdGguIA0KDQpUaGUgW1N0YXRlIG9mIEdsb2JhbCBBaXIgMjAxOSByZXBvcnRdKGh0dHBzOi8vd3d3LnN0YXRlb2ZnbG9iYWxhaXIub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvc29nYV8yMDE5X3JlcG9ydC5wZGYpe3RhcmdldD0iX2JsYW5rIn0NCndoaWNoIHVzZXMgZGF0YSBmcm9tIDIwMTcgc3RhdGVkIHRoYXQ6DQoNCj4gQWlyIHBvbGx1dGlvbiBpcyB0aGUgKipmaWZ0aCoqIGxlYWRpbmcgcmlzayBmYWN0b3IgZm9yIG1vcnRhbGl0eSB3b3JsZHdpZGUuIEl0IGlzIHJlc3BvbnNpYmxlIGZvciBtb3JlDQpkZWF0aHMgdGhhbiBtYW55IGJldHRlci1rbm93biByaXNrIGZhY3RvcnMgc3VjaCBhcyBtYWxudXRyaXRpb24sIGFsY29ob2wgdXNlLCBhbmQgcGh5c2ljYWwgaW5hY3Rpdml0eS4NCkVhY2ggeWVhciwgKiptb3JlKiogcGVvcGxlIGRpZSBmcm9tIGFpciBwb2xsdXRpb27igJNyZWxhdGVkIGRpc2Vhc2UgdGhhbiBmcm9tIHJvYWQgKip0cmFmZmljIGluanVyaWVzKiogb3IgKiptYWxhcmlhKiouDQoNCjxwIGFsaWduPSJjZW50ZXIiPg0KPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vd3d3LmhlYWx0aGVmZmVjdHMub3JnL3NpdGVzL2RlZmF1bHQvZmlsZXMvU29HQS1GaWd1cmVzLTAxLmpwZyI+DQo8L3A+DQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQ0KDQpUaGUgcmVwb3J0IGFsc28gc3RhdGVkIHRoYXQ6DQoNCj4gSW4gMjAxNywgYWlyIHBvbGx1dGlvbiBpcyBlc3RpbWF0ZWQgdG8gaGF2ZSBjb250cmlidXRlZCB0byBjbG9zZSB0byA1IG1pbGxpb24NCmRlYXRocyBnbG9iYWxseSDigJQgbmVhcmx5ICoqMSBpbiBldmVyeSAxMCBkZWF0aHMqKi4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCIyMDE3ZGVhdGhzLnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfZmFjdF9zaGVldC5wZGYpe3RhcmdldD0iX2JsYW5rIn0NCg0KVGhlIFtTdGF0ZSBvZiBHbG9iYWwgQWlyIDIwMTggcmVwb3J0XShodHRwczovL3d3dy5zdGF0ZW9mZ2xvYmFsYWlyLm9yZy9zaXRlcy9kZWZhdWx0L2ZpbGVzL3NvZ2EtMjAxOC1yZXBvcnQucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHVzaW5nIGRhdGEgZnJvbSAyMDE2IHdoaWNoIHNlcGFyYXRlZCBkaWZmZXJlbnQgdHlwZXMgb2YgYWlyIHBvbGx1dGlvbiwgZm91bmQgdGhhdCAqKnBhcnRpY3VsYXRlIHBvbGx1dGlvbiB3YXMgcGFydGljdWxhcmx5IGFzc29jaWF0ZWQgd2l0aCBtb3J0YWxpdHkqKi4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCIyMDE3bW9ydGFsaXR5LnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhLTIwMTgtcmVwb3J0LnBkZil7dGFyZ2V0PSJfYmxhbmsifQ0KDQpUaGUgMjAxOSByZXBvcnQgc2hvd3MgdGhhdCB0aGUgaGlnaGVzdCBsZXZlbHMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBwb2xsdXRpb24gb2NjdXJzIGluIEFmcmljYSBhbmQgQXNpYSBhbmQgdGhhdDoNCg0KPiBNb3JlIHRoYW4gKio5MCUqKiBvZiBwZW9wbGUgd29ybGR3aWRlIGxpdmUgaW4gYXJlYXMgKipleGNlZWRpbmcqKiB0aGUgV29ybGQgSGVhbHRoIE9yZ2FuaXphdGlvbiAoV0hPKSAqKkd1aWRlbGluZSoqIGZvciBoZWFsdGh5IGFpci4gTW9yZSB0aGFuIGhhbGYgbGl2ZSBpbiBhcmVhcyB0aGF0IGRvIG5vdCBldmVuIG1lZXQgV0hPJ3MgbGVhc3Qtc3RyaW5nZW50IGFpciBxdWFsaXR5IHRhcmdldC4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJQTXdvcmxkLnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly93d3cuc3RhdGVvZmdsb2JhbGFpci5vcmcvc2l0ZXMvZGVmYXVsdC9maWxlcy9zb2dhXzIwMTlfZmFjdF9zaGVldC5wZGYpe3RhcmdldD0iX2JsYW5rIn0NCg0KTG9va2luZyBhdCB0aGUgVVMgc3BlY2lmaWNhbGx5LCBhaXIgcG9sbHV0aW9uIGxldmVscyBhcmUgZ2VuZXJhbGx5IGltcHJvdmluZywgd2l0aCBkZWNsaW5pbmcgbmF0aW9uYWwgYWlyIHBvbGx1dGFudCBjb25jZW50cmF0aW9uIGF2ZXJhZ2VzIGFzIHNob3duIGZyb20gdGhlIDIwMTkgWypPdXIgTmF0aW9uJ3MgQWlyKl0oaHR0cHM6Ly9naXNwdWIuZXBhLmdvdi9haXIvdHJlbmRzcmVwb3J0LzIwMTkvI2hvbWUpe3RhcmdldD0iX2JsYW5rIn0gcmVwb3J0IGZyb20gdGhlIFVTIEVudmlyb25tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kgKEVQQSk6IA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIlVTLnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9naXNwdWIuZXBhLmdvdi9haXIvdHJlbmRzcmVwb3J0LzIwMTkvZG9jdW1lbnRhdGlvbi9BaXJUcmVuZHNfRmx5ZXIucGRmKXt0YXJnZXQ9Il9ibGFuayJ9DQoNCkhvd2V2ZXIsIGFpciBwb2xsdXRpb24gKipjb250aW51ZXMgdG8gY29udHJpYnV0ZSB0byBoZWFsdGggcmlzayBmb3IgQW1lcmljYW5zKiosIGluIHBhcnRpY3VsYXIgaW4gKipyZWdpb25zIHdpdGggaGlnaGVyIHRoYW4gbmF0aW9uYWwgYXZlcmFnZSByYXRlcyoqIG9mIHBvbGx1dGlvbiB0aGF0IGFjdHVhbGx5IGF0IHRpbWUgZXhjZWVkIHRoZSBXSE8ncyByZWNvbW1lbmRlZCBsZXZlbC4gDQpUaHVzLCBpdCBpcyBpbXBvcnRhbnQgdG8gb2J0YWluIGhpZ2ggc3BhdGlhbCBncmFudWxhcml0eSBpbiBlc3RpbWF0ZXMgb2YgYWlyIHBvbGx1dGlvbiBpbiBvcmRlciB0byBpZGVudGlmeSBsb2NhdGlvbnMgd2hlcmUgcG9wdWxhdGlvbnMgYXJlIGV4cGVyaWVuY2luZyBoYXJtZnVsIGxldmVscyBvZiBleHBvc3VyZS4NCg0KWW91IGNhbiBzZWUgdGhhdCBjdXJyZW50IGFpciBxdWFsaXR5IGNvbmRpdGlvbnMgYXQgdGhpcyBbd2Vic2l0ZV0oaHR0cHM6Ly9hcWljbi5vcmcvY2l0eS91c2EvKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCB5b3Ugd2lsbCBub3RpY2UgdmFyaWF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgY2l0aWVzLg0KDQpGb3IgZXhhbXBsZSwgaGVyZSBhcmUgdGhlIGNvbmRpdGlvbnMgaW4gVG9wZWthIEthbnNhcyBhdCB0aGUgdGltZSB0aGlzIGNhc2Ugc3R1ZHkgd2FzIGNyZWF0ZWQ6DQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiS2Fuc2FzLnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9hcWljbi5vcmcvY2l0eS91c2EvKXt0YXJnZXQ9Il9ibGFuayJ9DQoNCkl0IHJlcG9ydHMgcGFydGljdWxhdGUgdmFsdWVzIHVzaW5nIHdoYXQgaXMgY2FsbGVkIHRoZSBbQWlyIFF1YWxpdHkgSW5kZXhdKGh0dHBzOi8vd3d3LmFpcm5vdy5nb3YvaW5kZXguY2ZtP2FjdGlvbj1hcWliYXNpY3MuYXFpKXt0YXJnZXQ9Il9ibGFuayJ9IChBUUkpLg0KVGhpcyBbY2FsY3VsYXRvcl0oaHR0cHM6Ly9haXJub3cuZ292L2luZGV4LmNmbT9hY3Rpb249YWlybm93LmNhbGN1bGF0b3Ipe3RhcmdldD0iX2JsYW5rIn0gaW5kaWNhdGVzIHRoYXQgMTE0IEFRSSBpcyBlcXVpdmFsZW50IHRvIDQwLjcgdWcvbV4zXiBhbmQgaXMgY29uc2lkZXJlZCB1bmhlYWx0aHkgZm9yIHNlbnNpdGl2ZSBpbmRpdmlkdWFscy4NClRodXMsIHNvbWUgYXJlYXMgZXhjZWVkIHRoZSBXSE8gYW5udWFsIGV4cG9zdXJlIGd1aWRlbGluZSAoMTAgdWcvbV4zXikgYW5kIHRoaXMgbWF5IGFkdmVyc2VseSBhZmZlY3QgdGhlIGhlYWx0aCBvZiBwZW9wbGUgbGl2aW5nIGluIHRoZXNlIGxvY2F0aW9ucy4NCg0KQWR2ZXJzZSBoZWFsdGggZWZmZWN0cyBoYXZlIGJlZW4gYXNzb2NpYXRlZCB3aXRoIHBvcHVsYXRpb25zIGV4cGVyaWVuY2luZyBoaWdoZXIgcG9sbHV0aW9uIGV4cG9zdXJlIGRlc3BpdGUgdGhlIGxldmVscyBiZWluZyBiZWxvdyBzdWdnZXN0ZWQgZ3VpZGVsaW5lcy4gDQpBbHNvLCBpdCBhcHBlYXJzIHRoYXQgdGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgYW5kIHRoZSBpbmZsdWVuY2Ugb2Ygb3RoZXIgZGVtb2dyYXBoaWMgZmFjdG9ycyBtYXkgbWFrZSBzcGVjaWZpYyBwb3B1bGF0aW9ucyBtb3JlIGF0IHJpc2sgZm9yIGFkdmVyc2UgaGVhbHRoIGVmZmVjdHMgZHVlIHRvIGFpciBwb2xsdXRpb24uIA0KRm9yIGV4YW1wbGUsIHNlZSB0aGlzIFthcnRpY2xlXShodHRwczovL3d3dy5uZWptLm9yZy9kb2kvZnVsbC8xMC4xMDU2L05FSk1vYTE3MDI3NDcpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgZGV0YWlscy4NCg0KVGhlIG1vbml0b3IgZGF0YSB0aGF0IHdlIHdpbGwgdXNlIGluIHRoaXMgY2FzZSBzdHVkeSBjb21lIGZyb20gYSBzeXN0ZW0gb2YgbW9uaXRvcnMgaW4gd2hpY2ggcm91Z2hseSA5MCUgYXJlIGxvY2F0ZWQgd2l0aGluIGNpdGllcy4gDQpIZW5jZSwgdGhlcmUgaXMgYW4gKiplcXVpdHkgaXNzdWUqKiBpbiB0ZXJtcyBvZiBjYXB0dXJpbmcgdGhlIGFpciBwb2xsdXRpb24gbGV2ZWxzIG9mIG1vcmUgcnVyYWwgYXJlYXMuIA0KVG8gZ2V0IGEgYmV0dGVyIHNlbnNlIG9mIHRoZSBwb2xsdXRpb24gZXhwb3N1cmVzIGZvciB0aGUgaW5kaXZpZHVhbHMgbGl2aW5nIGluIHRoZXNlIGFyZWFzLCBtZXRob2RzIGxpa2UgbWFjaGluZSBsZWFybmluZyBjYW4gYmUgdXNlZnVsIHRvIGVzdGltYXRlIGFpciBwb2xsdXRpb24gbGV2ZWxzIGluICoqYXJlYXMgd2l0aCBsaXR0bGUgdG8gbm8gbW9uaXRvcmluZyoqLiANClNwZWNpZmljYWxseSwgdGhlc2UgbWV0aG9kcyBjYW4gYmUgdXNlZCB0byBlc3RpbWF0ZSBhaXIgcG9sbHV0aW9uIGluIHRoZXNlIGxvdyBtb25pdG9yaW5nIGFyZWFzIHNvIHRoYXQgd2UgY2FuIG1ha2UgYSBtYXAgbGlrZSB0aGlzIHdoZXJlIHdlIGhhdmUgYW5udWFsIGVzdGltYXRlcyBmb3IgYWxsIG9mIHRoZSBjb250aWd1b3VzIFVTOg0KDQo8cCBhbGlnbj0iY2VudGVyIj4NCiAgPGltZyB3aWR0aD0iNjAwIiBzcmM9Imh0dHBzOi8vYXJjLWFuZ2xlcmZpc2gtd2FzaHBvc3QtcHJvZC13YXNocG9zdC5zMy5hbWF6b25hd3MuY29tL3B1YmxpYy9TQVdPRUdCWE1WR1E3QVM1UFo2VVVPWDZGWS5wbmciPg0KPC9wPg0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vdXJsP3NhPWkmdXJsPWh0dHBzJTNBJTJGJTJGd3d3Lndhc2hpbmd0b25wb3N0LmNvbSUyRmJ1c2luZXNzJTJGMjAxOSUyRjEwJTJGMjMlMkZhaXItcG9sbHV0aW9uLWlzLWdldHRpbmctd29yc2UtZGF0YS1zaG93LW1vcmUtcGVvcGxlLWFyZS1keWluZyUyRiZwc2lnPUFPdlZhdzN2LVpEVEJQbkxQMk1ZdEtmM1VuZGomdXN0PTE1ODU3ODQ0NzkwNjgwMDAmc291cmNlPWltYWdlcyZjZD12ZmUmdmVkPTBDQUlRalJ4cUZ3b1RDUEN5bjlmeHhlZ0NGUUFBQUFBZEFBQUFBQkFkKXt0YXJnZXQ9Il9ibGFuayJ9DQoNClRoaXMgaXMgd2hhdCB3ZSBhaW0gdG8gYWNoaWV2ZSBpbiB0aGlzIGNhc2Ugc3R1ZHkuDQoNCiMgKipMaW1pdGF0aW9ucyoqDQoqKioNCg0KVGhlcmUgYXJlIHNvbWUgaW1wb3J0YW50IGNvbnNpZGVyYXRpb25zIHJlZ2FyZGluZyB0aGUgZGF0YSBhbmFseXNpcyBpbiB0aGlzIGNhc2Ugc3R1ZHkgdG8ga2VlcCBpbiBtaW5kOiANCg0KMS4gVGhlIGRhdGEgZG8gbm90IGluY2x1ZGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGNvbXBvc2l0aW9uIG9mIHBhcnRpY3VsYXRlIG1hdHRlci4gRGlmZmVyZW50IHR5cGVzIG9mIHBhcnRpY3VsYXRlcyBtYXkgYmUgbW9yZSBiZW5pZ24gb3IgZGVsZXRlcmlvdXMgZm9yIGhlYWx0aCBvdXRjb21lcy4NCg0KMi4gT3V0ZG9vciBwb2xsdXRpb24gbGV2ZWxzIGFyZSBub3QgbmVjZXNzYXJpbHkgYW4gaW5kaWNhdGlvbiBvZiBpbmRpdmlkdWFsIGV4cG9zdXJlcy4gUGVvcGxlIHNwZW5kIGRpZmZlcmluZyBhbW91bnRzIG9mIHRpbWUgaW5kb29ycyBhbmQgb3V0ZG9vcnMgYW5kIGFyZSBleHBvc2VkIHRvIGRpZmZlcmVudCBwb2xsdXRpb24gbGV2ZWxzIGluZG9vcnMuIFJlc2VhcmNoZXJzIGFyZSBub3cgZGV2ZWxvcGluZyBwZXJzb25hbCBtb25pdG9yaW5nIHN5c3RlbXMgdG8gdHJhY2sgYWlyIHBvbGx1dGlvbiBsZXZlbHMgb24gdGhlIHBlcnNvbmFsIGxldmVsLg0KDQozLiBPdXIgYW5hbHlzaXMgd2lsbCB1c2UgYW5udWFsIG1lYW4gZXN0aW1hdGVzIG9mIHBvbGx1dGlvbiBsZXZlbHMsIGJ1dCB0aGVzZSBjYW4gdmFyeSBncmVhdGx5IGJ5IHNlYXNvbiwgZGF5IGFuZCBldmVuIGhvdXIuIFRoZXJlIGFyZSBkYXRhIHNvdXJjZXMgdGhhdCBoYXZlIGZpbmVyIGxldmVscyBvZiB0ZW1wb3JhbCBkYXRhLCBob3dldmVyIHdlIGFyZSBpbnRlcmVzdGVkIGluIGxvbmcgdGVybSBleHBvc3VyZXMsIGFzIHRoZXNlIGFwcGVhciB0byBiZSB0aGUgbW9zdCBpbmZsdWVudGlhbCBmb3IgaGVhbHRoIG91dGNvbWVzLCBzbyB3ZSBjaG9zZSB0byB1c2UgYW5udWFsIGxldmVsIGRhdGEuIA0KDQoNCiMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKiB7I3doYXRhcmV0aGVkYXRhfQ0KKioqDQoNCldoZW4gdXNpbmcgbWFjaGluZSBsZWFybmluZyBmb3IgcHJlZGljdGlvbiwgdGhlcmUgYXJlIHR3byBtYWluIHR5cGVzIG9mIGRhdGEgb2YgaW50ZXJlc3Q6DQoNCjEuIEFuICoqY29udGludW91cyoqIG91dGNvbWUgdmFyaWFibGUgdGhhdCB3ZSB3YW50IHRvIHByZWRpY3QgDQoyLiBBIHNldCBvZiBmZWF0dXJlKHMpIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSB0aGF0IHdlIHVzZSB0byBwcmVkaWN0IHRoZSBvdXRjb21lIHZhcmlhYmxlDQoNClRoZSAqKm91dGNvbWUgdmFyaWFibGUqKiBpcyB3aGF0IGFyZSB0cnlpbmcgdG8gKipwcmVkaWN0KiouIA0KVG8gYnVpbGQgKG9yIHRyYWluKSBvdXIgbW9kZWwsIHdlIHVzZSBib3RoIHRoZSBvdXRjb21lIGFuZCBmZWF0dXJlcy4NClRoZSBnb2FsIGlzIHRvIGlkZW50aWZ5IGluZm9ybWF0aXZlIGZlYXR1cmVzIHRoYXQgY2FuIGV4cGxhaW4gYSBsYXJnZSBhbW91bnQgb2YgdmFyaWF0aW9uIGluIG91ciBvdXRjb21lIHZhcmlhYmxlLiANClVzaW5nIHRoaXMgbW9kZWwsIHdlIGNhbiB0aGVuIHByZWRpY3QgdGhlIG91dGNvbWUgZnJvbSBuZXcgb2JzZXJ2YXRpb25zIHdpdGggdGhlIHNhbWUgZmVhdHVyZXMgd2hlcmUgaGF2ZSBub3Qgb2JzZXJ2ZWQgdGhlIG91dGNvbWUuIA0KDQpBcyBhIHNpbXBsZSBleGFtcGxlLCBpbWFnaW5lIHRoYXQgd2UgaGF2ZSBkYXRhIGFib3V0IHRoZSBzYWxlcyBhbmQgY2hhcmFjdGVyaXN0aWNzIG9mIGNhcnMgZnJvbSBsYXN0IHllYXIgYW5kIHdlIHdhbnQgdG8gcHJlZGljdCB3aGljaCBjYXJzIG1pZ2h0IHNlbGwgd2VsbCB0aGlzIHllYXIuIA0KV2UgZG8gbm90IGhhdmUgdGhlIHNhbGVzIGRhdGEgeWV0IGZvciB0aGlzIHllYXIsIGJ1dCB3ZSBkbyBrbm93IHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2Ygb3VyIGNhcnMgZm9yIHRoaXMgeWVhci4gDQpXZSBjYW4gYnVpbGQgYSBtb2RlbCBvZiB0aGUgY2hhcmFjdGVyaXN0aWNzIHRoYXQgZXhwbGFpbmVkIHNhbGVzIGxhc3QgeWVhciB0byBlc3RpbWF0ZSB3aGF0IGNhcnMgbWlnaHQgc2VsbCB3ZWxsIHRoaXMgeWVhci4gDQpJbiB0aGlzIGNhc2UsIG91ciBvdXRjb21lIHZhcmlhYmxlIGlzIHRoZSBzYWxlcyBvZiBjYXJzLCB3aGlsZSB0aGUgZGlmZmVyZW50IGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgY2FycyBtYWtlIHVwIG91ciBmZWF0dXJlcy4NCg0KIyMjICoqU3RhcnQgd2l0aCBhIHF1ZXN0aW9uKioNCioqKg0KDQpUaGlzIGlzIHRoZSBtb3N0IGNvbW1vbmx5IG1pc3NlZCBzdGVwIHdoZW4gZGV2ZWxvcGluZyBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLiANCk1hY2hpbmUgbGVhcm5pbmcgY2FuIHZlcnkgZWFzaWx5IGJlIHR1cm5lZCBpbnRvIGFuIGVuZ2luZWVyaW5nIHByb2JsZW0uIA0KSnVzdCBkdW1wIHRoZSBvdXRjb21lIGFuZCB0aGUgZmVhdHVyZXMgaW50byBhIGJsYWNrIGJveCBhbGdvcml0aG0gYW5kIHZpb2xhISANCkJ1dCB0aGlzIGtpbmQgb2YgdGhpbmtpbmcgY2FuIGxlYWQgdG8gbWFqb3IgcHJvYmxlbXMuIEluIGdlbmVyYWwgZ29vZCBtYWNoaW5lIGxlYXJuaW5nIHF1ZXN0aW9uczoNCg0KMS4gSGF2ZSBhIHBsYXVzaWJsZSBleHBsYW5hdGlvbiBmb3Igd2h5IHRoZSBmZWF0dXJlcyBwcmVkaWN0IHRoZSBvdXRjb21lLiANCjIuIENvbnNpZGVyIHBvdGVudGlhbCB2YXJpYXRpb24gaW4gYm90aCB0aGUgZmVhdHVyZXMgYW5kIHRoZSBvdXRjb21lIG92ZXIgdGltZQ0KMy4gQXJlIGNvbnNpc3RlbnRseSByZS1ldmFsdWF0ZWQgb24gY3JpdGVyaWEgMSBhbmQgMiBvdmVyIHRpbWUuIA0KDQpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdhbnQgdG8gKipwcmVkaWN0KiogYWlyIHBvbGx1dGlvbiBsZXZlbHMuIA0KVG8gYnVpbGQgdGhpcyBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSwgb3VyICoqb3V0Y29tZSB2YXJpYWJsZSoqIGlzIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIChQTX4yLjV+KSBjYXB0dXJlZCBmcm9tIGFpciBwb2xsdXRpb24gbW9uaXRvcnMgaW4gdGhlIGNvbnRpZ3VvdXMgVVMgZnJvbSAyMDA4LiANCk91ciAqKmZlYXR1cmVzKiogKG9yIHByZWRpY3RvciB2YXJpYWJsZXMpIGluY2x1ZGUgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHJvYWQgZGVuc2l0eSwgdXJiYW5pemF0aW9uIGxldmVscywgYW5kIE5BU0Egc2F0ZWxsaXRlIGRhdGEuIA0KDQpBbGwgb2Ygb3VyIGRhdGEgd2FzIHByZXZpb3VzbHkgY29sbGVjdGVkIGJ5IGEgW3Jlc2VhcmNoZXJdKGh0dHA6Ly93d3cuYmlvc3RhdC5qaHNwaC5lZHUvfnJwZW5nLykgYXQgdGhlIFtKb2hucyBIb3BraW5zIFNjaG9vbCBvZiBQdWJsaWMgSGVhbHRoXShodHRwczovL3d3dy5qaHNwaC5lZHUvKSB3aG8gc3R1ZGllcyBhaXIgcG9sbHV0aW9uIGFuZCBjbGltYXRlIGNoYW5nZS4gDQoNCg0KIyMjICoqT3VyIG91dGNvbWUgdmFyaWFibGUqKg0KKioqDQoNClRoZSBtb25pdG9yIGRhdGEgdGhhdCB3ZSB3aWxsIGJlIHVzaW5nIGNvbWVzIGZyb20gKipbZ3JhdmltZXRyaWMgbW9uaXRvcnNdKGh0dHBzOi8vcHVibGljbGFiLm9yZy93aWtpL2ZpbHRlci1wbSl7dGFyZ2V0PSJfYmxhbmsifSoqIChzZWUgcGljdHVyZSBiZWxvdykgb3BlcmF0ZWQgYnkgdGhlIFVTIFtFbnZpcm9ubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5IChFUEEpXShodHRwczovL3d3dy5lcGEuZ292Lyl7dGFyZ2V0PSJfYmxhbmsifS4NCg0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSIxMDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJtb25pdG9yLnBuZyIpKQ0KYGBgDQoNCiMjIyMjIFtpbWFnZSBjdXJ0ZXN5IG9mIFtLaXJzdGVuIEtvZWhsZXJdKGh0dHBzOi8vd3d3Lmpoc3BoLmVkdS9mYWN1bHR5L2RpcmVjdG9yeS9wcm9maWxlLzI5Mjgva2lyc3Rlbi1rb2VobGVyKV0NCg0KVGhlc2UgbW9uaXRvcnMgdXNlIGEgZmlsdHJhdGlvbiBzeXN0ZW0gdG8gc3BlY2lmaWNhbGx5IGNhcHR1cmUgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIuIA0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjE1MHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImZpbHRlci5wbmciKSkNCmBgYA0KDQojIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vcHVibGljbGFiLm9yZy93aWtpL2ZpbHRlci1wbSl7dGFyZ2V0PSJfYmxhbmsifQ0KDQpUaGUgd2VpZ2h0IG9mIHRoaXMgcGFydGljdWxhdGUgbWF0dGVyIGlzIG1hbnVhbGx5IG1lYXN1cmVkIGRhaWx5IG9yIHdlZWtseS4gDQpGb3IgdGhlIEVQQSBzdGFuZGFyZCBvcGVyYXRpbmcgcHJvY2VkdXJlIGZvciBQTSBncmF2aW1ldHJpYyBhbmFseXNpcyBpbiAyMDA4LCB3ZSByZWZlciB0aGUgcmVhZGVyIHRvIFtoZXJlXShodHRwczovL3d3dzMuZXBhLmdvdi90dG5hbXRpMS9maWxlcy9hbWJpZW50L3BtMjUvc3BlYy9SVElHcmF2TWFzc1NPUEZJTkFMLnBkZil7dGFyZ2V0PSJfYmxhbmsifS4NCg0KPGRldGFpbHM+PHN1bW1hcnk+Rm9yIG1vcmUgb24gR3JhdmltZXRyaWMgYW5hbHlzaXMsIHlvdSBjYW4gZXhwYW5kIGhlcmUgPC9zdW1tYXJ5Pg0KDQpHcmF2aW1ldHJpYyBhbmFseXNpcyBpcyBhbHNvIHVzZWQgZm9yIFtlbWlzc2lvbiB0ZXN0aW5nXShodHRwczovL3d3dy5tdC5jb20vdXMvZW4vaG9tZS9hcHBsaWNhdGlvbnMvTGFib3JhdG9yeV93ZWlnaGluZy9lbWlzc2lvbnMtdGVzdGluZy1wYXJ0aWN1bGF0ZS1tYXR0ZXIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4gDQpUaGUgc2FtZSBpZGVhIGFwcGxpZXM6IGEgZnJlc2ggZmlsdGVyIGlzIGFwcGxpZWQgYW5kIHRoZSBkZXNpcmVkIGFtb3VudCBvZiB0aW1lIHBhc3NlcywgdGhlbiB0aGUgZmlsdGVyIGlzIHJlbW92ZWQgYW5kIHdlaWdoZWQuIA0KDQpUaGVyZSBhcmUgW290aGVyIG1vbml0b3Jpbmcgc3lzdGVtc10oaHR0cHM6Ly93d3cuc2Vuc2lyaW9uLmNvbS9lbi9hYm91dC11cy9uZXdzcm9vbS9zZW5zaXJpb24tc3BlY2lhbGlzdC1hcnRpY2xlcy9wYXJ0aWN1bGF0ZS1tYXR0ZXItc2Vuc2luZy1mb3ItYWlyLXF1YWxpdHktbWVhc3VyZW1lbnRzLyl7dGFyZ2V0PSJfYmxhbmsifSB0aGF0IGNhbiBwcm92aWRlIGhvdXJseSBtZWFzdXJlbWVudHMsIGJ1dCB3ZSB3aWxsIG5vdCBiZSB1c2luZyBkYXRhIGZyb20gdGhlc2UgbW9uaXRvcnMgaW4gb3VyIGFuYWx5c2lzLiANCkdyYXZpbWV0cmljIGFuYWx5c2lzIGlzIGNvbnNpZGVyZWQgdG8gYmUgYW1vbmcgdGhlIG1vc3QgYWNjdXJhdGUgbWV0aG9kcyBmb3IgbWVhc3VyaW5nIHBhcnRpY3VsYXRlIG1hdHRlci4NCg0KPC9kZXRhaWxzPg0KDQpJbiBvdXIgZGF0YSBzZXQsIHRoZSBgdmFsdWVgIGNvbHVtbiBpbmRpY2F0ZXMgdGhlIFBNfjIuNX4gbW9uaXRvciBhdmVyYWdlIGZvciAyMDA4IGluIG1hc3Mgb2YgZmluZSBwYXJ0aWNsZXMvdm9sdW1lIG9mIGFpciBmb3IgODc2IGdyYXZpbWV0cmljIG1vbml0b3JzLiANClRoZSB1bml0cyBhcmUgbWljcm9ncmFtcyBvZiBmaW5lIHBhcnRpY3VsYXRlIG1hdHRlciAoUE0pIHRoYXQgaXMgbGVzcyB0aGFuIDIuNSBtaWNyb21ldGVycyBpbiBkaWFtZXRlciBwZXIgY3ViaWMgbWV0ZXIgb2YgYWlyIC0gbWFzcyBjb25jZW50cmF0aW9uICh1Zy9tXjNeKS4NClJlY2FsbCB0aGUgV0hPIGV4cG9zdXJlIGd1aWRlbGluZSBpcyA8IDEwIHVnL21eM14gb24gYXZlcmFnZSBhbm51YWxseSBmb3IgUE1+Mi41fi4NCg0KIyMjICoqT3VyIGZlYXR1cmVzIChwcmVkaWN0b3IgdmFyaWFibGVzKSoqDQoqKioNCg0KVGhlcmUgYXJlIDQ4IGZlYXR1cmVzIHdpdGggdmFsdWVzIGZvciBlYWNoIG9mIHRoZSA4NzYgbW9uaXRvcnMgKG9ic2VydmF0aW9ucykuIA0KVGhlIGRhdGEgY29tZXMgZnJvbSB0aGUgVVMgW0Vudmlyb25tZW50YWwgUHJvdGVjdGlvbiBBZ2VuY3kgKEVQQSldKGh0dHBzOi8vd3d3LmVwYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LCB0aGUgW05hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlzdHJhdGlvbiAoTkFTQSldKGh0dHBzOi8vd3d3Lm5hc2EuZ292Lyl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlIFVTIFtDZW5zdXNdKGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YvYWJvdXQvd2hhdC9jZW5zdXMtYXQtYS1nbGFuY2UuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSwgYW5kIHRoZSBbTmF0aW9uYWwgQ2VudGVyIGZvciBIZWFsdGggU3RhdGlzdGljcyAoTkNIUyldKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9hYm91dC9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0uDQoNCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHNlZSBhIHRhYmxlIGFib3V0IHRoZSBzZXQgb2YgZmVhdHVyZXMgPC9zdW1tYXJ5Pg0KDQpWYXJpYWJsZSAgIHwgRGV0YWlscyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQ0KKippZCoqICB8IE1vbml0b3IgbnVtYmVyICA8YnI+IC0tIHRoZSBjb3VudHkgbnVtYmVyIGlzIGluZGljYXRlZCBiZWZvcmUgdGhlIGRlY2ltYWwgPGJyPiAtLSB0aGUgbW9uaXRvciBudW1iZXIgaXMgaW5kaWNhdGVkIGFmdGVyIHRoZSBkZWNpbWFsIDxicj4gICoqRXhhbXBsZSoqOiAxMDczLjAwMjMgIGlzIEplZmZlcnNvbiBjb3VudHkgKDEwNzMpIGFuZCAuMDAyMyBvbmUgb2YgOCBtb25pdG9ycyANCioqZmlwcyoqIHwgRmVkZXJhbCBpbmZvcm1hdGlvbiBwcm9jZXNzaW5nIHN0YW5kYXJkIG51bWJlciBmb3IgdGhlIGNvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkIDxicj4gLS0gNSBkaWdpdCBpZCBjb2RlIGZvciBjb3VudGllcyAoemVybyBpcyBvZnRlbiB0aGUgZmlyc3QgdmFsdWUgYW5kIHNvbWV0aW1lcyBpcyBub3Qgc2hvd24pIDxicj4gLS0gdGhlIGZpcnN0IDIgbnVtYmVycyBpbmRpY2F0ZSB0aGUgc3RhdGUgPGJyPiAtLSB0aGUgbGFzdCB0aHJlZSBudW1iZXJzIGluZGljYXRlIHRoZSBjb3VudHkgPGJyPiAgKipFeGFtcGxlKio6IEFsYWJhbWEncyBzdGF0ZSBjb2RlIGlzIDAxIGJlY2F1c2UgaXQgaXMgZmlyc3QgYWxwaGFiZXRpY2FsbHkgPGJyPiAobm90ZTogQWxhc2thIGFuZCBIYXdhaWkgYXJlIG5vdCBpbmNsdWRlZCBiZWNhdXNlIHRoZXkgYXJlIG5vdCBwYXJ0IG9mIHRoZSBjb250aWd1b3VzIFVTKSAgDQoqKkxhdCoqIHwgTGF0aXR1ZGUgb2YgdGhlIG1vbml0b3IgaW4gZGVncmVlcyAgDQoqKkxvbioqIHwgTG9uZ2l0dWRlIG9mIHRoZSBtb25pdG9yIGluIGRlZ3JlZXMgIA0KKipzdGF0ZSoqIHwgU3RhdGUgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZA0KKipjb3VudHkqKiB8IENvdW50eSB3aGVyZSB0aGUgbW9uaXRvciBpcyBsb2NhdGVkDQoqKmNpdHkqKiB8IENpdHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZA0KKipDTUFRKiogIHwgRXN0aW1hdGVkIHZhbHVlcyBvZiBhaXIgcG9sbHV0aW9uIGZyb20gYSBjb21wdXRhdGlvbmFsIG1vZGVsIGNhbGxlZCBbKipDb21tdW5pdHkgTXVsdGlzY2FsZSBBaXIgUXVhbGl0eSAoQ01BUSkqKl0oaHR0cHM6Ly93d3cuZXBhLmdvdi9jbWFxKXt0YXJnZXQ9Il9ibGFuayJ9IDxicj4gLS0gIEEgbW9uaXRvcmluZyBzeXN0ZW0gdGhhdCBzaW11bGF0ZXMgdGhlIHBoeXNpY3Mgb2YgdGhlIGF0bW9zcGhlcmUgdXNpbmcgY2hlbWlzdHJ5IGFuZCB3ZWF0aGVyIGRhdGEgdG8gcHJlZGljdCB0aGUgYWlyIHBvbGx1dGlvbiA8YnI+IC0tICoqKkRvZXMgbm90IHVzZSBhbnkgb2YgdGhlIFBNfjIuNX4gZ3JhdmltZXRyaWMgbW9uaXRvcmluZyBkYXRhLioqKiAoVGhlcmUgaXMgYSB2ZXJzaW9uIHRoYXQgZG9lcyB1c2UgdGhlIGdyYXZpbWV0cmljIG1vbml0b3JpbmcgZGF0YSwgYnV0IG5vdCB0aGlzIG9uZSEpIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBFUEENCioqemN0YSoqIHwgW1ppcCBDb2RlIFRhYnVsYXRpb24gQXJlYV0oaHR0cHM6Ly93d3cyLmNlbnN1cy5nb3YvZ2VvL3BkZnMvZWR1Y2F0aW9uL2Jyb2NodXJlcy9aQ1RBcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIFBvc3RhbCBaaXAgY29kZXMgYXJlIGNvbnZlcnRlZCBpbnRvICJnZW5lcmFsaXplZCBhcmVhbCByZXByZXNlbnRhdGlvbnMiIHRoYXQgYXJlIG5vbi1vdmVybGFwcGluZyAgPGJyPiAtLSBEYXRhIGZyb20gdGhlIDIwMTAgQ2Vuc3VzICANCioqemN0YV9hcmVhKiogfCBMYW5kIGFyZWEgb2YgdGhlIHppcCBjb2RlIGFyZWEgaW4gbWV0ZXJzIHNxdWFyZWQgIDxicj4gLS0gRGF0YSBmcm9tIHRoZSAyMDEwIENlbnN1cyAgDQoqKnpjdGFfcG9wKiogfCBQb3B1bGF0aW9uIGluIHRoZSB6aXAgY29kZSBhcmVhICA8YnI+IC0tIERhdGEgZnJvbSB0aGUgMjAxMCBDZW5zdXMgIA0KKippbXBfYTUwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSBXaXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciA8YnI+IC0tIEltcGVydmlvdXMgc3VyZmFjZSBhcmUgcm9hZHMsIGNvbmNyZXRlLCBwYXJraW5nIGxvdHMsIGJ1aWxkaW5ncyA8YnI+IC0tIFRoaXMgaXMgYSBtZWFzdXJlIG9mIGRldmVsb3BtZW50IA0KKippbXBfYTEwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvcg0KKippbXBfYTUwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAgDQoqKmltcF9hMTAwMDAqKiB8IEltcGVydmlvdXMgc3VyZmFjZSBtZWFzdXJlIDxicj4gLS0gIFdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgICANCioqaW1wX2ExNTAwMCoqIHwgSW1wZXJ2aW91cyBzdXJmYWNlIG1lYXN1cmUgPGJyPiAtLSAgV2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAgDQoqKmNvdW50eV9hcmVhKiogfCBMYW5kIGFyZWEgb2YgdGhlIGNvdW50eSBvZiB0aGUgbW9uaXRvciBpbiBtZXRlcnMgc3F1YXJlZCAgDQoqKmNvdW50eV9wb3AqKiB8IFBvcHVsYXRpb24gb2YgdGhlIGNvdW50eSBvZiB0aGUgbW9uaXRvciAgDQoqKkxvZ19kaXN0X3RvX3ByaXNlYyoqIHwgTG9nIChOYXR1cmFsIGxvZykgZGlzdGFuY2UgdG8gYSBwcmltYXJ5IG9yIHNlY29uZGFyeSByb2FkIGZyb20gdGhlIG1vbml0b3IgPGJyPiAtLSBIaWdod2F5IG9yIG1ham9yIHJvYWQgIA0KKipsb2dfcHJpX2xlbmd0aF81MDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpIDxicj4gLS0gSGlnaHdheXMgb25seSAgDQoqKmxvZ19wcmlfbGVuZ3RoXzEwMDAwKiogfCBDb3VudCBvZiBwcmltYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSA8YnI+IC0tIEhpZ2h3YXlzIG9ubHkgIA0KKipsb2dfcHJpX2xlbmd0aF8xNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAxNTAwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgPGJyPiAtLSBIaWdod2F5cyBvbmx5ICANCioqbG9nX3ByaV9sZW5ndGhfMjUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgcm9hZCBsZW5ndGggaW4gbWV0ZXJzIGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpIDxicj4gLS0gSGlnaHdheXMgb25seSAgDQoqKmxvZ19wcmlzZWNfbGVuZ3RoXzUwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDUwMCBtZXRlcnMgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgIDxicj4gLS0gSGlnaHdheSBhbmQgc2Vjb25kYXJ5IHJvYWRzICANCioqbG9nX3ByaXNlY19sZW5ndGhfMTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAgbWV0ZXJzIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICA8YnI+IC0tIEhpZ2h3YXkgYW5kIHNlY29uZGFyeSByb2FkcyAgDQoqKmxvZ19wcmlzZWNfbGVuZ3RoXzUwMDAqKiB8IENvdW50IG9mIHByaW1hcnkgYW5kIHNlY29uZGFyeSByb2FkIGxlbmd0aCBpbiBtZXRlcnMgaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiA1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIA0KKipsb2dfcHJpc2VjX2xlbmd0aF8xMDAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIA0KKipsb2dfcHJpc2VjX2xlbmd0aF8xNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgIA0KKipsb2dfcHJpc2VjX2xlbmd0aF8yNTAwMCoqIHwgQ291bnQgb2YgcHJpbWFyeSBhbmQgc2Vjb25kYXJ5IHJvYWQgbGVuZ3RoIGluIG1ldGVycyBpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDI1MDAwIG1ldGVycyBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgPGJyPiAtLSBIaWdod2F5IGFuZCBzZWNvbmRhcnkgcm9hZHMgICAgICANCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzEwMDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDEwMDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICANCioqbG9nX25laV8yMDA4X3BtMjVfc3VtXzE1MDAwKiogfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgDQoqKmxvZ19uZWlfMjAwOF9wbTI1X3N1bV8yNTAwMCoqIHwgVG9ucyBvZiBlbWlzc2lvbnMgZnJvbSBtYWpvciBzb3VyY2VzIGRhdGEgYmFzZSAoYW5udWFsIGRhdGEpIHN1bSBvZiBhbGwgc291cmNlcyB3aXRoaW4gYSBjaXJjbGUgd2l0aCBhIHJhZGl1cyBvZiAyNTAwMCBtZXRlcnMgb2YgZGlzdGFuY2UgYXJvdW5kIHRoZSBtb25pdG9yIChOYXR1cmFsIGxvZykgICAgIA0KKipsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMTAwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMTAwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAgDQoqKmxvZ19uZWlfMjAwOF9wbTEwX3N1bV8xNTAwMCoqfCBUb25zIG9mIGVtaXNzaW9ucyBmcm9tIG1ham9yIHNvdXJjZXMgZGF0YSBiYXNlIChhbm51YWwgZGF0YSkgc3VtIG9mIGFsbCBzb3VyY2VzIHdpdGhpbiBhIGNpcmNsZSB3aXRoIGEgcmFkaXVzIG9mIDE1MDAwIG1ldGVycyBvZiBkaXN0YW5jZSBhcm91bmQgdGhlIG1vbml0b3IgKE5hdHVyYWwgbG9nKSAgICAgIA0KKipsb2dfbmVpXzIwMDhfcG0xMF9zdW1fMjUwMDAqKiB8IFRvbnMgb2YgZW1pc3Npb25zIGZyb20gbWFqb3Igc291cmNlcyBkYXRhIGJhc2UgKGFubnVhbCBkYXRhKSBzdW0gb2YgYWxsIHNvdXJjZXMgd2l0aGluIGEgY2lyY2xlIHdpdGggYSByYWRpdXMgb2YgMjUwMDAgbWV0ZXJzIG9mIGRpc3RhbmNlIGFyb3VuZCB0aGUgbW9uaXRvciAoTmF0dXJhbCBsb2cpICAgICAgDQoqKnBvcGRlbnNfY291bnR5KiogfCBQb3B1bGF0aW9uIGRlbnNpdHkgKG51bWJlciBvZiBwZW9wbGUgcGVyIGtpbG9tZXRlciBzcXVhcmVkIGFyZWEgb2YgdGhlIGNvdW50eSkNCioqcG9wZGVuc196Y3RhKiogfCBQb3B1bGF0aW9uIGRlbnNpdHkgKG51bWJlciBvZiBwZW9wbGUgcGVyIGtpbG9tZXRlciBzcXVhcmVkIGFyZWEgb2YgemN0YSkNCioqbm9ocyoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIGlzIHRoYXQgKipkbyBub3QgaGF2ZSBhIGhpZ2ggc2Nob29sIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMNCioqc29tZWhzKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgKipzb21lIGhpZ2ggc2Nob29sIGVkdWNhdGlvbioqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMNCioqaHMqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nIGEgKipoaWdoIHNjaG9vbCBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzICANCioqc29tZWNvbGxlZ2UqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBjb21wbGV0aW5nICoqc29tZSBjb2xsZWdlIGVkdWNhdGlvbioqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgDQoqKmFzc29jaWF0ZSoqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIHdob3NlIGhpZ2hlc3QgZm9ybWFsIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQgd2FzIGNvbXBsZXRpbmcgYW4gKiphc3NvY2lhdGUgZGVncmVlKiogPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyANCioqYmFjaGVsb3IqKiB8IFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqYmFjaGVsb3IncyBkZWdyZWUqKiA8YnI+IC0tIERhdGEgZnJvbSB0aGUgQ2Vuc3VzIA0KKipncmFkKiogfCBQZXJjZW50YWdlIG9mIHBlb3BsZSBpbiB6Y3RhIGFyZWEgd2hlcmUgdGhlIG1vbml0b3Igd2hvc2UgaGlnaGVzdCBmb3JtYWwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCB3YXMgYSAqKmdyYWR1YXRlIGRlZ3JlZSoqIDxicj4gLS0gRGF0YSBmcm9tIHRoZSBDZW5zdXMgDQoqKnBvdioqIHwgUGVyY2VudGFnZSBvZiBwZW9wbGUgaW4gemN0YSBhcmVhIHdoZXJlIHRoZSBtb25pdG9yIGlzIHRoYXQgbGl2ZWQgaW4gWyoqcG92ZXJ0eSoqXShodHRwczovL2FzcGUuaGhzLmdvdi8yMDA4LWhocy1wb3ZlcnR5LWd1aWRlbGluZXMpIGluIDIwMDggLSBvciB3b3VsZCBpdCBoYXZlIGJlZW4gMjAwNyBndWlkZWxpbmVzPz9odHRwczovL2FzcGUuaGhzLmdvdi8yMDA3LWhocy1wb3ZlcnR5LWd1aWRlbGluZXMgPGJyPiAtLSBEYXRhIGZyb20gdGhlIENlbnN1cyAgDQoqKmhzX29ybGVzcyoqIHwgIFBlcmNlbnRhZ2Ugb2YgcGVvcGxlIGluIHpjdGEgYXJlYSB3aGVyZSB0aGUgbW9uaXRvciB3aG9zZSBoaWdoZXN0IGZvcm1hbCBlZHVjYXRpb25hbCBhdHRhaW5tZW50IHdhcyBhICoqaGlnaCBzY2hvb2wgZGVncmVlIG9yIGxlc3MqKiAoc3VtIG9mIG5vaHMsIHNvbWVocywgYW5kIGhzKSAgDQoqKnVyYzIwMTMqKiB8IFsyMDEzIFVyYmFuLXJ1cmFsIGNsYXNzaWZpY2F0aW9uXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvZGF0YS9zZXJpZXMvc3JfMDIvc3IwMl8xNjYucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIHRoZSBjb3VudHkgd2hlcmUgdGhlIG1vbml0b3IgaXMgbG9jYXRlZCA8YnI+IC0tIDYgY2F0ZWdvcnkgdmFyaWFibGUgLSAxIGlzIHRvdGFsbHkgdXJiYW4gNiBpcyBjb21wbGV0ZWx5IHJ1cmFsIDxicj4gIC0tIERhdGEgZnJvbSB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3NdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gICAgIA0KKip1cmMyMDA2KiogfCBbMjAwNiBVcmJhbi1ydXJhbCBjbGFzc2lmaWNhdGlvbl0oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2RhdGEvc2VyaWVzL3NyXzAyL3NyMDJfMTU0LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIGlzIGxvY2F0ZWQgPGJyPiAtLSA2IGNhdGVnb3J5IHZhcmlhYmxlIC0gMSBpcyB0b3RhbGx5IHVyYmFuIDYgaXMgY29tcGxldGVseSBydXJhbCA8YnI+IC0tIERhdGEgZnJvbSB0aGUgW05hdGlvbmFsIENlbnRlciBmb3IgSGVhbHRoIFN0YXRpc3RpY3NdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gICAgIA0KKiphb2QqKiB8IEFlcm9zb2wgT3B0aWNhbCBEZXB0aCBtZWFzdXJlbWVudCBmcm9tIGEgTkFTQSBzYXRlbGxpdGUgPGJyPiAtLSBiYXNlZCBvbiB0aGUgZGlmZnJhY3Rpb24gb2YgYSBsYXNlciA8YnI+IC0tIHVzZWQgYXMgYSBwcm94eSBvZiBwYXJ0aWN1bGF0ZSBwb2xsdXRpb24gPGJyPiAtLSB1bml0LWxlc3MgLSBoaWdoZXIgdmFsdWUgaW5kaWNhdGVzIG1vcmUgcG9sbHV0aW9uIDxicj4gLS0gRGF0YSBmcm9tIE5BU0EgIA0KDQo8L2RldGFpbHM+DQoNCk1hbnkgb2YgdGhlc2UgZmVhdHVyZXMgaGF2ZSB0byBkbyB3aXRoIHRoZSBjaXJjdWxhciBhcmVhIGFyb3VuZCB0aGUgbW9uaXRvciBjYWxsZWQgdGhlICJidWZmZXIiLiBUaGVzZSBhcmUgaWxsdXN0cmF0ZWQgaW4gdGhlIGZvbGxvd2luZyBmaWd1cmU6DQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4MDBweCIsfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInJlZ3Jlc3Npb24ucG5nIikpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3B1Ym1lZC8xNTI5MjkwNil7dGFyZ2V0PSJfYmxhbmsifQ0KDQoNCg0KIyAqKkRhdGEgSW1wb3J0KioNCioqKg0KDQpBbGwgb2Ygb3VyIGRhdGEgd2FzIHByZXZpb3VzbHkgY29sbGVjdGVkIGJ5IGEgW3Jlc2VhcmNoZXJdKGh0dHA6Ly93d3cuYmlvc3RhdC5qaHNwaC5lZHUvfnJwZW5nLykgYXQgdGhlIFtKb2hucyBIb3BraW5zIFNjaG9vbCBvZiBQdWJsaWMgSGVhbHRoXShodHRwczovL3d3dy5qaHNwaC5lZHUvKSB3aG8gc3R1ZGllcyBhaXIgcG9sbHV0aW9uIGFuZCBjbGltYXRlIGNoYW5nZS4gDQoNCldlIGhhdmUgb25lIENTViBmaWxlIHRoYXQgY29udGFpbnMgYm90aCBvdXIgc2luZ2xlICoqb3V0Y29tZSB2YXJpYWJsZSoqIGFuZCBhbGwgb2Ygb3VyICoqZmVhdHVyZXMqKiAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykuDQoNCk5leHQsIHdlIGltcG9ydCBvdXIgZGF0YSBpbnRvIFIgbm93IHNvIHRoYXQgd2UgY2FuIGV4cGxvcmUgdGhlIGRhdGEgZnVydGhlci4gDQpXZSB3aWxsIGNhbGwgb3VyIGRhdGEgb2JqZWN0IGBwbWAgZm9yIHBhcnRpY3VsYXRlIG1hdHRlci4gDQpXZSBpbXBvcnQgdGhlIGRhdGEgdXNpbmcgdGhlIGByZWFkX2NzdigpYCBmdW5jdGlvbiBmcm9tIHRoZSBgcmVhZHJgIHBhY2thZ2UuIA0KYGBge3J9DQpwbSA8LSByZWFkcjo6cmVhZF9jc3YoaGVyZSgiZG9jcyIsICJwbTI1X2RhdGEuY3N2IikpDQpgYGANCg0KDQoNCiMgKipEYXRhIEV4cGxvcmF0aW9uIGFuZCBXcmFuZ2xpbmcqKg0KKioqDQoNClRoZSBmaXJzdCBzdGVwIGluIHBlcmZvcm1pbmcgYW55IGRhdGEgYW5hbHlzaXMgaXMgdG8gZXhwbG9yZSB0aGUgZGF0YS4gDQoNCkZvciBleGFtcGxlLCB3ZSBtaWdodCB3YW50IHRvIGJldHRlciB1bmRlcnN0YW5kIHRoZSB2YXJpYWJsZXMgaW5jbHVkZWQgaW4gdGhlIGRhdGEsIGFzIHdlIG1heSBsZWFybiBhYm91dCBpbXBvcnRhbnQgZGV0YWlscyBhYm91dCB0aGUgZGF0YSB0aGF0IHdlIHNob3VsZCBrZWVwIGluIG1pbmQgYXMgd2UgdHJ5IHRvIHByZWRpY3Qgb3VyIG91dGNvbWUgdmFyaWFibGUuDQoNCkZpcnN0LCBsZXQncyBqdXN0IGdldCBhIGdlbmVyYWwgc2Vuc2Ugb2Ygb3VyIGRhdGEuIA0KV2UgY2FuIGRvIHRoYXQgdXNpbmcgdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgKGl0IGlzIGFsc28gaW4gdGhlIGB0aWJibGVgIHBhY2thZ2UpLg0KDQpXZSB3aWxsIGFsc28gdXNlIHRoZSBgJT4lYCBwaXBlLCB3aGljaCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgdGhlIGlucHV0IGZvciBsYXRlciBzZXF1ZW50aWFsIHN0ZXBzLiANCg0KVGhpcyB3aWxsIG1ha2UgbW9yZSBzZW5zZSB3aGVuIHdlIGhhdmUgbXVsdGlwbGUgc2VxdWVudGlhbCBzdGVwcyB1c2luZyB0aGUgc2FtZSBkYXRhIG9iamVjdC4gDQoNClRvIHVzZSB0aGUgcGlwZSBub3RhdGlvbiB3ZSBuZWVkIHRvIGluc3RhbGwgYW5kIGxvYWQgYGRwbHlyYCBhcyB3ZWxsLg0KDQpGb3IgZXhhbXBsZSwgaGVyZSB3ZSBzdGFydCB3aXRoIGBwbWAgZGF0YSBvYmplY3QgYW5kICJwaXBlIiB0aGUgb2JqZWN0IGludG8gYXMgaW5wdXQgaW50byB0aGUgYGdsaW1wc2UoKWAgZnVuY3Rpb24uIA0KVGhlIG91dHB1dCBpcyBpcyBhbiBvdmVydmlldyBvZiB3aGF0IGlzIGluIHRoZSBgcG1gIG9iamVjdCBzdWNoIGFzIHRoZSBudW1iZXIgb2Ygcm93cyBhbmQgY29sdW1ucywgYWxsIHRoZSBjb2x1bW4gbmFtZXMsIHRoZSBkYXRhIHR5cGVzIGZvciBlYWNoIGNvbHVtbiBhbmQgdGhlIGZpcnN0IHZpZXcgdmFsdWVzIGluIGVhY2ggY29sdW1uLiANClRoZSBvdXRwdXQgYmVsb3cgaXMgc2Nyb2xsYWJsZSBzbyB5b3UgY2FuIHNlZSBldmVyeXRoaW5nIGZyb20gdGhlIGBnbGltcHNlKClgIGZ1bmN0aW9uLiANCg0KIyMjIyB7LnNjcm9sbGFibGUgfQ0KDQpgYGB7cn0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCnBtICU+JQ0KICBkcGx5cjo6Z2xpbXBzZSgpDQpgYGANCg0KIyMjIw0KDQpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDg3NiBtb25pdG9ycyAocm93cykgYW5kIHRoYXQgd2UgaGF2ZSA1MCB0b3RhbCB2YXJpYWJsZXMgKGNvbHVtbnMpIC0gb25lIG9mIHdoaWNoIGlzIHRoZSBvdXRjb21lIHZhcmlhYmxlLiBJbiB0aGlzIGNhc2UsIHRoZSBvdXRjb21lIHZhcmlhYmxlIGlzIGNhbGxlZCBgdmFsdWVgLiANCg0KTm90aWNlIHRoYXQgc29tZSBvZiB0aGUgdmFyaWFibGVzIHRoYXQgd2Ugd291bGQgdGhpbmsgb2YgYXMgZmFjdG9ycyAob3IgY2F0ZWdvcmljYWwgZGF0YSkgYXJlIGN1cnJlbnRseSBvZiBjbGFzcyBjaGFyYWN0ZXIgYXMgaW5kaWNhdGVkIGJ5IHRoZSBgPGNocj5gIGp1c3QgdG8gdGhlIHJpZ2h0IG9mIHRoZSBjb2x1bW4gbmFtZXMvdmFyaWFibGUgbmFtZXMgaW4gdGhlIGBnbGltcHNlKClgIG91dHB1dC4gVGhpcyBtZWFucyB0aGF0IHRoZSB2YXJpYWJsZSB2YWx1ZXMgYXJlIGNoYXJhY3RlciBzdHJpbmdzLCBzdWNoIGFzIHdvcmRzIG9yIHBocmFzZXMuIA0KDQpUaGUgb3RoZXIgdmFyaWFibGVzIGFyZSBvZiBjbGFzcyBgPGRibD5gLCB3aGljaCBzdGFuZHMgZm9yIGRvdWJsZSBwcmVjaXNpb24gd2hpY2ggaW5kaWNhdGVzIHRoYXQgdGhlIGFyZSBudW1lcmljIGFuZCB0aGF0IHRoZXkgaGF2ZSBkZWNpbWFsIHZhbHVlcy4gSW4gY29udHJhc3QsIG9uZSBjb3VsZCBoYXZlIGludGVnZXIgdmFsdWVzIHdoaWNoIHdvdWxkIG5vdCBhbGxvdyBmb3IgZGVjaW1hbCBudW1iZXJzLiBIZXJlIGlzIGEgW2xpbmtdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RvdWJsZS1wcmVjaXNpb25fZmxvYXRpbmctcG9pbnRfZm9ybWF0KXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIGRvdWJsZSBwcmVjaXNpb24gbnVtZXJpYyB2YWx1ZXMuDQoNCkFub3RoZXIgY29tbW9uIGRhdGEgY2xhc3MgaXMgZmFjdG9yIHdoaWNoIGlzIGFiYnJldmlhdGVkIGxpa2UgdGhpczogYDxmY3Q+YC4gQSBmYWN0b3IgaXMgc29tZXRoaW5nIHRoYXQgaGFzIHVuaXF1ZSBsZXZlbHMgYnV0IHRoZXJlIGlzIG5vIGFwcHJlY2lhYmxlIG9yZGVyIHRvIHRoZSBsZXZlbHMuIEZvciBleGFtcGxlIHdlIGNhbiBoYXZlIGEgbnVtZXJpYyB2YWx1ZSB0aGF0IGlzIGp1c3QgYW4gaWQgdGhhdCB3ZSB3YW50IHRvIGJlIGludGVycHJldGVkIGFzIGp1c3QgYSB1bmlxdWUgbGV2ZWwgYW5kIG5vdCBhcyB0aGUgbnVtYmVyIHRoYXQgaXQgd291bGQgdHlwaWNhbGx5IGluZGljYXRlLiBUaGlzIHdvdWxkIGJlIHVzZWZ1bCBmb3Igc2V2ZXJhbCBvZiBvdXIgdmFyaWFibGVzOg0KDQoxLiB0aGUgbW9uaXRvciBJRCAoYGlkYCkNCjIuIHRoZSBGZWRlcmFsIEluZm9ybWF0aW9uIFByb2Nlc3NpbmcgU3RhbmRhcmQgbnVtYmVyIGZvciB0aGUgY291bnR5IHdoZXJlIHRoZSBtb25pdG9yIHdhcyBsb2NhdGVkIChgZmlwc2ApDQozLiB0aGUgemlwIGNvZGUgdGFidWxhdGlvbiBhcmVhIChgemN0YWApDQoNCk5vbmUgb2YgdGhlIHZhbHVlcyBhY3R1YWxseSBoYXZlIGFueSByZWFsIG51bWVyaWMgbWVhbmluZywgc28gd2Ugd2FudCB0byBtYWtlIHN1cmUgdGhhdCBSIGRvZXMgbm90IGludGVycHJldCB0aGVtIGFzIGlmIHRoZXkgZG8uIA0KDQpTbyBsZXQncyBjb252ZXJ0IHRoZXNlIHZhcmlhYmxlcyBpbnRvIGZhY3RvcnMuIA0KV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGBhY3Jvc3MoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSBhbmQgdGhlIGBhcy5mYWN0b3IoKWAgYmFzZSBmdW5jdGlvbi4gDQpUaGUgYGFjcm9zcygpYCBmdW5jdGlvbiBoYXMgdHdvIG1haW4gYXJndW1lbnRzOiAoaSkgdGhlIGNvbHVtbnMgeW91IHdhbnQgdG8gb3BlcmF0ZSBvbiBhbmQgKGlpKSB0aGUgZnVuY3Rpb24gb3IgbGlzdCBvZiBmdW5jdGlvbnMgdG8gYXBwbHkgdG8gZWFjaCBjb2x1bW4uIA0KDQpJbiB0aGlzIGNhc2UsIHdlIGFyZSBhbHNvIHVzaW5nIHRoZSBgbWFncml0dHJgIGFzc2lnbm1lbnQgcGlwZSBvciBkb3VibGUgcGlwZSB0aGF0IGxvb2tzIGxpa2UgdGhpcyBgJTw+JWAgb2YgdGhlIGBtYWdyaXR0cmAgcGFja2FnZS4gDQpUaGlzIGFsbG93cyB1cyB1c2UgdGhlIGBwbWAgZGF0YSBhcyBpbnB1dCwgYnV0IGFsc28gcmVhc3NpZ25zIHRoZSBvdXRwdXQgdG8gdGhlIHNhbWUgZGF0YSBvYmplY3QgbmFtZS4NCg0KIyMjIyB7LnNjcm9sbGFibGUgfQ0KDQpgYGB7cn0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCnBtICU8PiUNCiAgbXV0YXRlKGFjcm9zcyhjKGlkLCBmaXBzLCB6Y3RhKSwgYXMuZmFjdG9yKSkgDQoNCmdsaW1wc2UocG0pDQpgYGANCg0KIyMjIw0KDQpHcmVhdCEgTm93IHdlIGNhbiBzZWUgdGhhdCB0aGVzZSB2YXJpYWJsZXMgYXJlIG5vdyBmYWN0b3JzIGFzIGluZGljYXRlZCBieSBgPGZjdD5gIGFmdGVyIHRoZSB2YXJpYWJsZSBuYW1lLg0KDQoNCg0KIyMjICoqYHNraW1gIHBhY2thZ2UqKg0KKioqDQoNClRoZSBgc2tpbSgpYCBmdW5jdGlvbiBvZiB0aGUgYHNraW1yYCBwYWNrYWdlIGlzIGFsc28gcmVhbGx5IGhlbHBmdWwgZm9yIGdldHRpbmcgYSBnZW5lcmFsIHNlbnNlIG9mIHlvdXIgZGF0YS4NCkJ5IGRlc2lnbiwgaXQgcHJvdmlkZXMgc3VtbWFyeSBzdGF0aXN0aWNzIGFib3V0IHZhcmlhYmxlcyBpbiB0aGUgZGF0YSBzZXQuIA0KDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCg0KYGBge3J9DQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhDQpza2ltcjo6c2tpbShwbSkNCmBgYA0KDQojIyMjDQoNCk5vdGljZSBob3cgdGhlcmUgaXMgYSBjb2x1bW4gY2FsbGVkIGBuX21pc3NpbmdgIGFib3V0IHRoZSBudW1iZXIgb2YgdmFsdWVzIHRoYXQgYXJlIG1pc3NpbmcuIA0KDQpUaGlzIGlzIGFsc28gaW5kaWNhdGVkIGJ5IHRoZSBgY29tcGxldGVfcmF0ZWAgdmFyaWFibGUgKG9yIG1pc3NpbmcvbnVtYmVyIG9mIG9ic2VydmF0aW9ucykuIA0KDQpJbiBvdXIgZGF0YSBzZXQsIGl0IGxvb2tzIGxpa2Ugb3VyIGRhdGEgZG8gbm90IGNvbnRhaW4gYW55IG1pc3NpbmcgZGF0YS4gDQoNCkFsc28gbm90aWNlIGhvdyB0aGUgZnVuY3Rpb24gcHJvdmlkZXMgc2VwYXJhdGUgdGFibGVzIG9mIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgZWFjaCBkYXRhIHR5cGU6IGNoYXJhY3RlciwgZmFjdG9yIGFuZCBudW1lcmljLiANCg0KTmV4dCwgdGhlIGBuX3VucWl1ZWAgY29sdW1uIHNob3dzIHVzIHRoZSBudW1iZXIgb2YgdW5pcXVlIHZhbHVlcyBmb3IgZWFjaCBvZiBvdXIgY29sdW1ucy4gDQpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDQ5IHN0YXRlcyByZXByZXNlbnRlZCBpbiB0aGUgZGF0YS4NCg0KV2UgY2FuIHNlZSB0aGF0IGZvciBtYW55IHZhcmlhYmxlcyB0aGVyZSBhcmUgbWFueSBsb3cgdmFsdWVzIGFzIHRoZSBkaXN0cmlidXRpb24gc2hvd3MgdHdvIHBlYWtzLCBvbmUgbmVhciB6ZXJvIGFuZCBhbm90aGVyIHdpdGggYSBoaWdoZXIgdmFsdWUuIA0KDQpUaGlzIGlzIHRydWUgZm9yIHRoZSBgaW1wYCB2YXJpYWJsZXMgKG1lYXN1cmVzIG9mIGRldmVsb3BtZW50KSwgdGhlIGBuZWlgIHZhcmlhYmxlcyAobWVhc3VyZXMgb2YgZW1pc3Npb24gc291cmNlcykgYW5kIHRoZSByb2FkIGRlbnNpdHkgdmFyaWFibGVzLiANCg0KV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlIHJhbmdlIG9mIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyBpcyB2ZXJ5IGxhcmdlLCBpbiBwYXJ0aWN1bGFyIHRoZSBhcmVhIGFuZCBwb3B1bGF0aW9uIHJlbGF0ZWQgdmFyaWFibGVzLg0KDQoNCkxldCdzIHRha2UgYSBsb29rIHRvIHNlZSB3aGljaCBzdGF0ZXMgYXJlIGluY2x1ZGVkIHVzaW5nIHRoZSBgZGlzdGluY3QoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZToNCg0KYGBge3IsIGV2YWwgPSBGQUxTRX0gDQpwbSAlPiUgDQogIGRwbHlyOjpkaXN0aW5jdChzdGF0ZSkgDQpgYGANCg0KDQpTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0Og0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KcG0gJT4lIA0KICBkaXN0aW5jdChzdGF0ZSkgJT4lDQojIHRoaXMgYWxsb3dzIHVzIHRvIHNob3cgdGhlIGZ1bGwgb3V0cHV0IGluIHRoZSByZW5kZXJlZCBybWFya2Rvd24NCiBwcmludChuID0gMWUzKQ0KYGBgDQojIyMjDQoNCkl0IGxvb2tzIGxpa2UgIkRpc3RyaWN0IG9mIENvbHVtYmlhIiBpcyBiZWluZyBpbmNsdWRlZCBhcyBhIHN0YXRlLiANCldlIGNhbiBzZWUgdGhhdCBBbGFza2EgYW5kIEhhd2FpaSBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSBkYXRhLg0KDQpMZXQncyBhbHNvIHRha2UgYSBsb29rIHRvIHNlZSBob3cgbWFueSBtb25pdG9ycyB0aGVyZSBhcmUgaW4gYSBmZXcgY2l0aWVzLiBXZSBjYW4gdXNlIHRoZSBgZmlsdGVyKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gZG8gc28uIEZvciBleGFtcGxlLCBsZXQncyBsb29rIGF0IEFsYnVxdWVycXVlLCBOZXcgTWV4aWNvLiANCg0KYGBge3J9DQpwbSAlPiUgZHBseXI6OmZpbHRlcihjaXR5ID09ICJBbGJ1cXVlcnF1ZSIpDQoNCmBgYA0KDQpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgd2VyZSBvbmx5IHR3byBtb25pdG9ycyBpbiB0aGUgY2l0eSBvZiBBbGJ1cXVlcnF1ZSBpbiAyMDA2LiBMZXQncyBjb21wYXJlIHRoaXMgd2l0aCBCYWx0aW1vcmUuDQoNCmBgYHtyfQ0KcG0gJT4lIGRwbHlyOjpmaWx0ZXIoY2l0eSA9PSAiQmFsdGltb3JlIikNCg0KYGBgDQoNClRoZXJlIHdlcmUgaW4gY29udHJhc3QgZml2ZSBtb25pdG9ycyBmb3IgdGhlIGNpdHkgb2YgQmFsdGltb3JlLCBkZXNwaXRlIHRoZSBmYWN0IHRoYXQgaWYgd2UgdGFrZSBhIGxvb2sgYXQgdGhlIGxhbmQgYXJlYSBhbmQgcG9wdWxhdGlvbiBvZiB0aGUgY291bnRpZXMgZm9yIEJsYXRpbW9yZSBDaXR5IGFuZCBBbGJ1cXVlcnF1ZSwgd2UgY2FuIHNlZSB0aGF0IHRoZXkgaGFkIHZlcnkgc2ltaWxhciBsYW5kIGFyZWEgYW5kIHBvcHVsYXRpb25zLg0KDQpgYGB7cn0NCnBtICU+JSANCiAgZHBseXI6OmZpbHRlcihjaXR5ID09ICJCYWx0aW1vcmUiKSAlPiUgDQogIHNlbGVjdChjb3VudHlfYXJlYTpjb3VudHlfcG9wKQ0KcG0gJT4lIA0KICBkcGx5cjo6ZmlsdGVyKGNpdHkgPT0gIkFsYnVxdWVycXVlIikgJT4lDQogIHNlbGVjdChjb3VudHlfYXJlYTpjb3VudHlfcG9wKQ0KDQpgYGANCg0KSW4gZmFjdCwgdGhlIGNvdW50eSBjb250YWluaW5nIEFsYnVlcnF1ZSBoYWQgYSBsYXJnZXIgcG9wdWxhdGlvbi4gVGh1cyB0aGUgbWVhc3VyZW1lbnRzIGZvciBBbGJ1cXVlcnF1ZSB3ZXJlIG5vdCBhcyB0aG9yb3VnaCBhcyB0aGV5IHdlcmUgZm9yIEJhbHRpbW9yZS4NCg0KVGhpcyBtYXkgYmUgZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhlIG1vbml0b3IgdmFsdWVzIHdlcmUgbG93ZXIgaW4gQWxidXF1ZXJxdWUuIEl0IGlzIGludGVyZXN0aW5nIHRvIG5vdGUgaGVyZSB0aGF0IHRoZSBDTUFRIHZhbHVlcyBhcmUgcXVpdGUgc2ltaWxhciBmb3IgYm90aCBjaXRpZXMuDQoNCg0KIyMgKipFdmFsdWF0ZSBjb3JyZWxhdGlvbioqDQoqKioNCg0KSW4gcHJlZGljdGlvbiBhbmFseXNlcywgaXQgaXMgYWxzbyB1c2VmdWwgdG8gZXZhbHVhdGUgaWYgYW55IG9mIHRoZSB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQuIFdoeSBzaG91bGQgd2UgY2FyZSBhYm91dCB0aGlzPw0KDQpJZiB3ZSBhcmUgdXNpbmcgYSBsaW5lYXIgcmVncmVzc2lvbiB0byBtb2RlbCBvdXIgZGF0YSB0aGVuIHdlIG1pZ2h0IHJ1biBpbnRvIGEgcHJvYmxlbSBjYWxsZWQgbXVsdGljb2xpbmVhcml0eSB3aGljaCBjYW4gbGVhZCB1cyB0byBtaXNpbnRlcnByZXQgd2hhdCBpcyByZWFsbHkgcHJlZGljdGl2ZSBvZiBvdXIgb3V0Y29tZSB2YXJpYWJsZS4gVGhpcyBwaGVub21lbm9uIG9jY3VycyB3aGVuIHRoZSBwcmVkaWN0b3IgdmFyaWFibGVzIGFjdHVhbGx5IHByZWRpY3Qgb25lIGFub3RoZXIuIFNlZSBbdGhpcyBjYXNlIHN0dWR5XShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vb2NzLWJwLVJUQy1hbmFseXNpcy8pIGZvciBhIGRlZXBlciBleHBsYW5hdGlvbiBhYm91dCB0aGlzLiANCg0KQW5vdGhlciByZWFzb24gd2Ugc2hvdWxkIGxvb2sgb3V0IGZvciBjb3JyZWxhdGlvbiBpcyB0aGF0IHdlIGRvbid0IHdhbnQgdG8gaW5jbHVkZSByZWR1bmRhbnQgdmFyaWFibGVzLiBUaGlzIGNhbiBhZGQgdW5uZWNlc3Nhcnkgbm9pc2UgdG8gb3VyIGFsZ29yaXRobSBjYXVzaW5nIGEgcmVkdWN0aW9uIGluIHByZWRpY3Rpb24gYWNjdXJhY3kgYW5kIGl0IGNhbiBjYXVzZSBvdXIgYWxnb3JpdGhtIHRvIGJlIHVubmVjZXNzYXJpbHkgc2xvd2VyLiBGaW5hbGx5LCBpdCBjYW4gYWxzbyBtYWtlIGl0IGRpZmZpY3VsdCB0byBpbnRlcnByZXQgd2hhdCB2YXJpYWJsZXMgYXJlIGFjdHVhbGx5IHByZWRpY3RpdmUuDQoNCkludHVpdGl2ZWx5IHdlIGNhbiBleHBlY3Qgc29tZSBvZiBvdXIgdmFyaWFibGVzIHRvIGJlIGNvcnJlbGF0ZWQuDQoNCkxldCdzIGZpcnN0IHRha2UgYSBsb29rIGF0IGFsbCBvZiBvdXIgbnVtZXJpYyB2YXJpYWJsZXMgd2l0aCB0aGVgY29ycnBsb3RgIHBhY2thZ2U6DQpUaGUgYGNvcnJwbG90YCBwYWNrYWdlIGlzIGFub3RoZXIgb3B0aW9uIHRvIGxvb2sgYXQgY29ycmVsYXRpb24gYW1vbmcgcG9zc2libGUgcHJlZGljdG9ycywgYW5kIHBhcnRpY3VsYXJseSB1c2VmdWwgaWYgd2UgaGF2ZSBtYW55IHByZWRpY3RvcnMuIA0KDQpGaXJzdCwgd2UgY2FsY3VsYXRlIHRoZSBQZWFyc29uIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyBiZXR3ZWVuIGFsbCBmZWF0dXJlcyBwYWlyd2lzZSB1c2luZyB0aGUgYGNvcigpYCBmdW5jdGlvbiBvZiB0aGUgYHN0YXRzYCBwYWNrYWdlICh3aGljaCBpcyBsb2FkZWQgYXV0b21hdGljYWxseSkuIFRoZW4gd2UgdXNlIHRoZSBgY29ycnBsb3Q6OmNvcnJwbG90KClgIGZ1bmN0aW9uLiANCg0KYGBge3J9DQpQTV9jb3IgPC0gY29yKHBtICU+JSBkcGx5cjo6c2VsZWN0X2lmKGlzLm51bWVyaWMpKQ0KY29ycnBsb3Q6OmNvcnJwbG90KFBNX2NvciwgdGwuY2V4ID0gMC41KQ0KYGBgDQpUaGUgYHRsLmNleCA9IDAuNWAgYXJndW1lbnQgY29udHJvbHMgdGhlIHNpemUgb2YgdGhlIHRleHQgbGFiZWwuIA0KDQpXZSBjYW4gYWxzbyBwbG90IHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiB0aGUgUGVhcnNvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgdXNpbmcgdGhlIGBhYnMoKWAgZnVuY3Rpb24gZnJvbSBiYXNlIFIgYW5kIGNoYW5nZSB0aGUgb3JkZXIgb2YgdGhlIGNvbHVtbnMuICANCmBgYHtyfQ0KY29ycnBsb3QoYWJzKFBNX2NvciksIG9yZGVyID0gImhjbHVzdCIsIHRsLmNleCA9IDAuNSwgY2wubGltID0gYygwLCAxKSkNCg0KYGBgDQoNClRoZXJlIGFyZSBzZXZlcmFsIG9wdGlvbnMgZm9yIG9yZGVyaW5nIHRoZSB2YXJpYWJsZXMuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2NvcnJwbG90L3ZpZ25ldHRlcy9jb3JycGxvdC1pbnRyby5odG1sKSBmb3IgbW9yZSBvcHRpb25zLiBIZXJlIHdlIHdpbGwgdXNlIHRoZSAiaGNsdXN0IiBvcHRpb24gZm9yIG9yZGVyaW5nIGJ5IFtoaWVyYXJjaGljYWwgY2x1c3RlcmluZ10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSGllcmFyY2hpY2FsX2NsdXN0ZXJpbmcpIC0gd2hpY2ggd2lsbCBvcmRlciB0aGUgdmFyaWFibGVzIGJ5IGhvdyBzaW1pbGFyIHRoZXkgYXJlIHRvIG9uZSBhbm90aGVyLg0KDQpUaGUgYGNsLmxpbSA9IGMoMCwgMSlgIGFyZ3VtZW50IGxpbWl0cyB0aGUgY29sb3IgbGFiZWwgdG8gYmUgYmV0d2VlbiAwIGFuZCAxLiANCg0KDQpXZSBjYW4gc2VlIHRoYXQgdGhlIGRldmVsb3BtZW50IHZhcmlhYmxlcyAoYGltcGApIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIgYXMgd2UgbWlnaHQgZXhwZWN0LiANCldlIGFsc28gc2VlIHRoYXQgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMgc2VlbSB0byBiZSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlciwgYW5kIHRoZSBlbWlzc2lvbiB2YXJpYWJsZXMgc2VlbSB0byBiZSBjb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlci4gDQoNCg0KQWxzbyBub3RpY2UgdGhhdCBub25lIG9mIHRoZSBwcmVkaWN0b3JzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG91ciBvdXRjb21lIHZhcmlhYmxlIChgdmFsdWVgKS4NCg0KV2UgY2FuIHRha2UgYWxzbyB0YWtlIGEgY2xvc2VyIGxvb2sgIHVzaW5nIHRoZSBgZ2djb3JyKClgIGZ1bmN0aW9uIGFuZCB0aGUgYGdncGFpcnMoKWAgZnVuY3Rpb24gb2YgdGhlIGBHR2FsbHlgIHBhY2thZ2UuIA0KDQpUbyBzZWxlY3Qgb3VyIHZhcmlhYmxlcyBvZiBpbnRlcmVzdCB3ZSBjYW4gdXNlIHRoZSBgc2VsZWN0KClgIGZ1bmN0aW9uIHdpdGggdGhlIGBjb250YWlucygpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlLiANCg0KRmlyc3QgbGV0J3MgbG9vayBhdCB0aGUgYGltcGAvZGV2ZWxvcG1lbnQgdmFyaWFibGVzLiANCldlIGNhbiBjaGFuZ2UgdGhlIGRlZmF1bHQgY29sb3IgcGFsZXR0ZSAoYHBhbGV0dGUgPSAiUmRCdSJgKSBhbmQgYWRkIG9uIA0KY29ycmVsYXRpb24gY29lZmZpY2llbnRzIHRvIHRoZSBwbG90IChgbGFiZWwgPSBUUlVFYCkuDQoNCmBgYHtyLCBvdXQud2lkdGggPSAiNDAwcHgifQ0Kc2VsZWN0KHBtLCBjb250YWlucygiaW1wIikpICU+JQ0KICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgbGFiZWwgPSBUUlVFKQ0KDQpzZWxlY3QocG0sIGNvbnRhaW5zKCJpbXAiKSkgJT4lDQogIGdncGFpcnMoKQ0KYGBgDQoNCg0KDQpJbmRlZWQsIHdlIGNhbiBzZWUgdGhhdCBgaW1wX2ExMDAwYCBhbmQgYGltcF9hNTAwYCBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQsIGFzIHdlbGwgYXMgYGltcF9hMTAwMDBgLCBgaW1wX2ExNTAwMGAuDQoNCk5leHQsIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSByb2FkIGRlbnNpdHkgZGF0YToNCg0KYGBge3IsIGZpZy53ZWlnaHQ9MTJ9DQpzZWxlY3QocG0sIGNvbnRhaW5zKCJwcmkiKSkgJT4lDQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCBoanVzdCA9IC44NSwgc2l6ZSA9IDMsDQogICAgICAgbGF5b3V0LmV4cD0yLCBsYWJlbCA9IFRSVUUpDQpgYGANCg0KV2UgY2FuIHNlZSB0aGF0IG1hbnkgb2YgdGhlIHJvYWQgZGVuc2l0eSB2YXJpYWJsZXMgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIsIHdoaWxlIG90aGVycyBhcmUgbGVzcyBzby4NCg0KRmluYWxseSBsZXQncyBsb29rIGF0IHRoZSBlbWlzc2lvbiB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0Kc2VsZWN0KHBtLCBjb250YWlucygibmVpIikpICU+JQ0KICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgaGp1c3QgPSAuODUsIHNpemUgPSAzLA0KICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQ0KDQpzZWxlY3QocG0sIGNvbnRhaW5zKCJuZWkiKSkgJT4lDQogIGdncGFpcnMoKQ0KYGBgDQoNCldlIHdvdWxkIGFsc28gZXhwZWN0IHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgZGF0YSBtaWdodCBjb3JyZWxhdGUgd2l0aCBzb21lIG9mIHRoZXNlIHZhcmlhYmxlcy4gDQpMZXQncyB0YWtlIGEgbG9vay4NCg0KYGBge3J9DQpwbSAlPiUNCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIHBvcGRlbnNfY291bnR5LCANCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCkgJT4lDQogIGdnY29ycihwYWxldHRlID0gIlJkQnUiLCAgaGp1c3QgPSAuODUsIHNpemUgPSAzLA0KICAgICAgIGxheW91dC5leHA9MiwgbGFiZWwgPSBUUlVFKQ0KDQpwbSAlPiUNCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIHBvcGRlbnNfY291bnR5LCANCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgY291bnR5X3BvcCkgJT4lDQogIGdncGFpcnMoKQ0KYGBgDQoNCg0KSW50ZXJlc3RpbmcsIHNvIHRoZXNlIHZhcmlhYmxlcyBkb24ndCBhcHBlYXIgdG8gYmUgaGlnaGx5IGNvcnJlbGF0ZWQsIHRoZXJlZm9yZSB3ZSBtaWdodCBuZWVkIHZhcmlhYmxlcyBmcm9tIGVhY2ggb2YgdGhlIGNhdGVnb3JpZXMgdG8gcHJlZGljdCBvdXIgbW9uaXRvciBQTX4yLjV+IHBvbGx1dGlvbiB2YWx1ZXMuDQoNCkJlY2F1c2Ugc29tZSB2YXJpYWJsZXMgaW4gb3VyIGRhdGEgaGF2ZSBleHRyZW1lIHZhbHVlcywgaXQgbWlnaHQgYmUgZ29vZCB0byB0YWtlIGEgbG9nIHRyYW5zZm9ybWF0aW9uLiBUaGlzIGNhbiBhZmZlY3Qgb3VyIGVzdGltYXRlcyBvZiBjb3JyZWxhdGlvbi4gDQpgYGB7cn0NCnBtICU+JQ0KICBtdXRhdGUobG9nX3BvcGRlbnNfY291bnR5PSBsb2cocG9wZGVuc19jb3VudHkpKSAlPiUNCnNlbGVjdChsb2dfbmVpXzIwMDhfcG0yNV9zdW1fMTAwMDAsIGxvZ19wb3BkZW5zX2NvdW50eSwgDQogICAgICAgbG9nX3ByaV9sZW5ndGhfMTAwMDAsIGltcF9hMTAwMDApICU+JQ0KICBnZ2NvcnIocGFsZXR0ZSA9ICJSZEJ1IiwgIGhqdXN0ID0gLjg1LCBzaXplID0gMywNCiAgICAgICBsYXlvdXQuZXhwPTIsIGxhYmVsID0gVFJVRSkNCg0KcG0gJT4lDQogIG11dGF0ZShsb2dfcG9wZGVuc19jb3VudHk9IGxvZyhwb3BkZW5zX2NvdW50eSkpICU+JQ0KICBtdXRhdGUobG9nX3BvcF9jb3VudHkgPSBsb2coY291bnR5X3BvcCkpICU+JQ0Kc2VsZWN0KGxvZ19uZWlfMjAwOF9wbTI1X3N1bV8xMDAwMCwgbG9nX3BvcGRlbnNfY291bnR5LCANCiAgICAgICBsb2dfcHJpX2xlbmd0aF8xMDAwMCwgaW1wX2ExMDAwMCwgbG9nX3BvcF9jb3VudHkpICU+JQ0KICBnZ3BhaXJzKCkNCmBgYA0KDQpJbmRlZWQgdGhpcyBpbmNyZWFzZWQgdGhlIGNvcnJlbGF0aW9uLCBidXQgdmFyaWFibGVzIGZyb20gZWFjaCBvZiB0aGVzZSBjYXRlZ29yaWVzIG1heSBzdGlsbCBwcm92ZSB0byBiZSB1c2VmdWwgZm9yIHByZWRpY3Rpb24uDQoNCk5vdyB0aGF0IHdlIGhhdmUgYSBzZW5zZSBvZiB3aGF0IG91ciBkYXRhIGFyZSwgd2UgY2FuIGdldCBzdGFydGVkIHdpdGggYnVpbGRpbmcgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbi4gDQoNCjwhLS0tQVBfREVXX1F1aXotLT4NCg0KPGlmcmFtZSBzdHlsZT0ibWFyZ2luOjAgYXV0bzsgbWluLXdpZHRoOiAxMDAlOyIgaWQ9IkFQX0RFV19RdWl6SWZyYW1lIiBjbGFzcz0iaW50ZXJhY3RpdmUiIHNyYz0iaHR0cHM6Ly9yc2Nvbm5lY3QuYmlvc3RhdC5qaHNwaC5lZHUvT0NTX0FQX0RFV19RdWl6LyIgc2Nyb2xsaW5nPSJubyIgZnJhbWVib3JkZXI9Im5vIj48L2lmcmFtZT4NCg0KPCEtLS0tLS0tLS0tLS0tLS0tPg0KDQojICoqV2hhdCBpcyBtYWNoaW5lIGxlYXJuaW5nPyoqICB7I3doYXRpc21sfQ0KKioqDQoNCllvdSBtYXkgaGF2ZSBsZWFybmVkIGFib3V0IHRoZSBjZW50cmFsIGRvZ21hIG9mIHN0YXRpc3RpY3MgdGhhdCB5b3Ugc2FtcGxlIGZyb20gYSBwb3B1bGF0aW9uLg0KDQohW10oaW1nL2NkaTEucG5nKQ0KDQpUaGVuIHlvdSB1c2UgdGhlIHNhbXBsZSB0byB0cnkgdG8gZ3Vlc3Mgd2hhdCBpcyBoYXBwZW5pbmcgaW4gdGhlIHBvcHVsYXRpb24uDQoNCiFbXShpbWcvY2RpMi5wbmcpDQoNCkZvciBwcmVkaWN0aW9uIHdlIGhhdmUgYSBzaW1pbGFyIHNhbXBsaW5nIHByb2JsZW0NCg0KIVtdKGltZy9jZHAxLnBuZykNCg0KQnV0IG5vdyB3ZSBhcmUgdHJ5aW5nIHRvIGJ1aWxkIGEgcnVsZSB0aGF0IGNhbiBiZSB1c2VkIHRvIHByZWRpY3QgYSBzaW5nbGUgb2JzZXJ2YXRpb24ncyB2YWx1ZSBvZiBzb21lIGNoYXJhY3RlcmlzdGljIHVzaW5nIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgb3RoZXIgb2JzZXJ2YXRpb25zLiANCg0KIVtdKGltZy9jZHAyLnBuZykNCg0KTGV0J3MgbWFrZSB0aGlzIG1vcmUgY29uY3JldGUuDQoNCklmIHlvdSByZWNhbGwgZnJvbSB0aGUgW1doYXQgYXJlIHRoZSBkYXRhP10oI3doYXRhcmV0aGVkYXRhKSBzZWN0aW9uIGFib3ZlLCB3aGVuIHdlIGFyZSB1c2luZyBtYWNoaW5lIGxlYXJuaW5nIGZvciBwcmVkaWN0aW9uLCBvdXIgZGF0YSBjb25zaXN0cyBvZjogDQoNCjEuIEFuICoqY29udGludW91cyoqIG91dGNvbWUgdmFyaWFibGUgdGhhdCB3ZSB3YW50IHRvIHByZWRpY3QgDQoyLiBBIHNldCBvZiBmZWF0dXJlKHMpIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKSB0aGF0IHdlIHVzZSB0byBwcmVkaWN0IHRoZSBvdXRjb21lIHZhcmlhYmxlDQoNCldlIHdpbGwgdXNlICRZJCB0byBkZW5vdGUgdGhlIG91dGNvbWUgdmFyaWFibGUgYW5kICRYID0gKFhfMSwgXGRvdHMsIFhfcCkkIHRvIGRlbm90ZSAkcCQgZGlmZmVyZW50IGZlYXR1cmVzIChvciBwcmVkaWN0b3IgdmFyaWFibGVzKS4gDQpCZWNhdXNlIG91ciBvdXRjb21lIHZhcmlhYmxlIGlzICoqY29udGludW91cyoqIChhcyBvcHBvc2VkIHRvIGNhdGVnb3JpY2FsKSwgd2UgYXJlIGludGVyZXN0ZWQgaW4gYSBwYXJ0aWN1bGFyIHR5cGUgb2YgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0uIA0KDQpPdXIgZ29hbCBpcyB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHRoYXQgdXNlcyB0aGUgZmVhdHVyZXMgJFgkIGFzIGlucHV0IGFuZCBwcmVkaWN0cyBhbiBvdXRjb21lIHZhcmlhYmxlIChvciBhaXIgcG9sbHV0aW9uIGxldmVscykgaW4gdGhlIHNpdHVhdGlvbiB3aGVyZSB3ZSBkbyBub3Qga25vdyB0aGUgb3V0Y29tZSB2YXJpYWJsZS4gDQoNClRoZSB3YXkgd2UgZG8gdGhpcyBpcyB0byB1c2UgZGF0YSB3aGVyZSB3ZSBoYXZlIGJvdGggdGhlIGZlYXR1cmVzICQoWF8xPXhfMSwgXGRvdHMgWF9wPXhfcCkkIGFuZCB0aGUgYWN0dWFsIG91dGNvbWUgJFkkIGRhdGEgdG8gX3RyYWluXyBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHRvIHByZWRpY3QgdGhlIG91dGNvbWUsIHdoaWNoIHdlIGNhbGwgJFxoYXR7WX0kLiAgDQoNCldoZW4gd2Ugc2F5IHRyYWluIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gd2UgbWVhbiB0aGF0IHdlIGVzdGltYXRlIGEgZnVuY3Rpb24gJGYkIHRoYXQgdXNlcyB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcyAkWCQgYXMgaW5wdXQgb3IgJFxoYXR7WX0gPSBmKFgpJC4gDQoNCiMjICoqTUwgYXMgYW4gb3B0aW1pemF0aW9uIHByb2JsZW0qKg0KDQpJZiB3ZSBhcmUgZG9pbmcgYSBnb29kIGpvYiwgdGhlbiBvdXIgcHJlZGljdGVkIG91dGNvbWUgJFxoYXR7WX0kIHNob3VsZCBjbG9zZWx5IG1hdGNoIG91ciBhY3R1YWwgb3V0Y29tZSAkWSQgdGhhdCB3ZSBvYnNlcnZlZC4gDQoNCkluIHRoaXMgd2F5LCB3ZSBjYW4gdGhpbmsgb2YgbWFjaGluZSBsZWFybmluZyAoTUwpIGFzIGFuIG9wdGltaXphdGlvbiBwcm9ibGVtIHRoYXQgdHJpZXMgdG8gbWluaW1pemUgdGhlIGRpc3RhbmNlIGJldHdlZW4gJFxoYXR7WX0gPSBmKFgpJCBhbmQgJFkkLiANCg0KJCRkKFkgLSBmKFgpKSQkDQpUaGUgY2hvaWNlIG9mIGRpc3RhbmNlIG1ldHJpYyAkZChcY2RvdCkkIGNhbiBiZSB0aGUgbWVhbiBvZiB0aGUgYWJzb2x1dGUgb3Igc3F1YXJlZCBkaWZmZXJlbmNlIG9yIHNvbWV0aGluZyBtb3JlIGNvbXBsaWNhdGVkLiANCg0KTXVjaCBvZiB0aGUgZmllbGRzIG9mIHN0YXRpc3RpY3MgYW5kIGNvbXB1dGVyIHNjaWVuY2UgYXJlIGZvY3VzZWQgb24gZGVmaW5pbmcgJGYkIGFuZCAkZCQuDQoNCiMjICoqVGhlIHBhcnRzIG9mIGFuIE1MIHByb2JsZW0qKg0KDQpUbyBzZXQgdXAgYSBtYWNoaW5lIGxlYXJuaW5nIChNTCkgcHJvYmxlbSwgd2UgbmVlZCBhIGZldyBjb21wb25lbnRzLg0KVG8gc29sdmUgYSAoc3RhbmRhcmQpIG1hY2hpbmUgbGVhcm5pbmcgcHJvYmxlbSB5b3UgbmVlZDogDQoNCjEuIEEgZGF0YSBzZXQgdG8gdHJhaW4gZnJvbS4gDQoyLiBBbiBhbGdvcml0aG0gb3Igc2V0IG9mIGFsZ29yaXRobXMgeW91IGNhbiB1c2UgdG8gdHJ5IHZhbHVlcyBvZiAkZiQNCjMuIEEgZGlzdGFuY2UgbWV0cmljICRkJCBmb3IgbWVhc3VyaW5nIGhvdyBjbG9zZSAkWSQgaXMgdG8gJFxoYXR7WX0kDQo0LiBBIGRlZmluaXRpb24gb2Ygd2hhdCBhICJnb29kIiBkaXN0YW5jZSBpcw0KDQpXaGlsZSBlYWNoIG9mIHRoZXNlIGNvbXBvbmVudHMgaXMgYSBfdGVjaG5pY2FsXyBwcm9ibGVtLCB0aGVyZSBoYXMgYmVlbiBhIHRvbiBvZiB3b3JrIGFkZHJlc3NpbmcgdGhvc2UgdGVjaG5pY2FsIGRldGFpbHMuIFRoZSBtb3N0IHByZXNzaW5nIG9wZW4gaXNzdWUgaW4gbWFjaGluZSBsZWFybmluZyBpcyByZWFsaXppbmcgdGhhdCB0aG91Z2ggdGhlc2UgYXJlIF90ZWNobmljYWxfIHN0ZXBzIHRoZXkgYXJlIG5vdCBfb2JqZWN0aXZlXyBzdGVwcy4gSW4gb3RoZXIgd29yZHMsIGhvdyB5b3UgY2hvb3NlIHRoZSBkYXRhLCBhbGdvcml0aG0sIG1ldHJpYywgYW5kIGRlZmluaXRpb24gb2YgImdvb2QiIHNheXMgd2hhdCB5b3UgdmFsdWUgYW5kIGNhbiBkcmFtYXRpY2FsbHkgY2hhbmdlIHRoZSByZXN1bHRzLiBBIGNvdXBsZSBvZiBjYXNlcyB3aGVyZSB0aGlzIHdhcyBhIGJpZyBkZWFsIGFyZTogDQoNCjEuIFtNYWNoaW5lIGxlYXJuaW5nIGZvciByZWNpZGl2aXNtXShodHRwczovL3d3dy5wcm9wdWJsaWNhLm9yZy9hcnRpY2xlL21hY2hpbmUtYmlhcy1yaXNrLWFzc2Vzc21lbnRzLWluLWNyaW1pbmFsLXNlbnRlbmNpbmcpIC0gcGVvcGxlIGJ1aWx0IE1MIG1vZGVscyB0byBwcmVkaWN0IHdobyB3b3VsZCByZS1jb21taXQgYSBjcmltZS4gQnV0IHRoZXNlIHByZWRpY3Rpb25zIHdlcmUgYmFzZWQgb24gaGlzdG9yaWNhbGx5IGJpYXNlZCBkYXRhIHdoaWNoIGxlZCB0byBiaWFzZWQgcHJlZGljdGlvbnMgYWJvdXQgd2hvIHdvdWxkIGNvbW1pdCBuZXcgY3JpbWVzLiANCjIuIFtEZWNpZGluZyBob3cgc2VsZiBkcml2aW5nIGNhcnMgc2hvdWxkIGFjdF0oaHR0cHM6Ly93d3cubmF0dXJlLmNvbS9hcnRpY2xlcy9kNDE1ODYtMDE4LTA3MTM1LTApIC0gc2VsZiBkcml2aW5nIGNhcnMgd2lsbCBoYXZlIHRvIG1ha2UgZGVjaXNpb25zIGFib3V0IGhvdyB0byBkcml2ZSwgd2hvIHRoZXkgbWlnaHQgaW5qdXJlLCBhbmQgaG93IHRvIGF2b2lkIGFjY2lkZW50cy4gRGVwZW5kaW5nIG9uIG91ciBjaG9pY2VzIGZvciAkZiQgYW5kICRkJCB0aGVzZSBtaWdodCBsZWFkIHRvIHdpbGRseSBkaWZmZXJlbnQga2luZHMgb2Ygc2VsZiBkcml2aW5nIGNhcnMuIFRyeSBvdXQgdGhlIFttb3JhbG1hY2hpbmVdKGh0dHA6Ly9tb3JhbG1hY2hpbmUubWl0LmVkdS8pIHRvIHNlZSBob3cgdGhpcyBsb29rcyBpbiBwcmFjdGljZS4gDQoNCk5vdyB0aGF0IHdlIGtub3cgYSBiaXQgbW9yZSBhYm91dCBtYWNoaW5lIGxlYXJuaW5nLCBsZXQncyBidWlsZCBhIG1vZGVsIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBsZXZlbHMgdXNpbmcgdGhlIGB0aWR5bW9kZWxzYCBmcmFtZXdvcmsuIA0KDQojICoqTWFjaGluZSBsZWFybmluZyB3aXRoIGB0aWR5bW9kZWxzYCoqDQoqKioNClRoZSBnb2FsIGlzIHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdXNlcyB0aGUgZmVhdHVyZXMgYXMgaW5wdXQgYW5kIHByZWRpY3RzIGEgb3V0Y29tZSB2YXJpYWJsZSAob3IgYWlyIHBvbGx1dGlvbiBsZXZlbHMpIGluIHRoZSBzaXR1YXRpb24gd2hlcmUgd2UgZG8gbm90IGtub3cgdGhlIG91dGNvbWUgdmFyaWFibGUuIA0KDQpUaGUgd2F5IHdlIGRvIHRoaXMgaXMgdG8gdXNlIGRhdGEgd2hlcmUgd2UgaGF2ZSBib3RoIHRoZSBpbnB1dCBhbmQgb3V0cHV0IGRhdGEgdG8gX3RyYWluXyBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtLiANCg0KVG8gdHJhaW4gYSBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobSwgd2Ugd2lsbCB1c2UgdGhlIGB0aWR5bW9kZWxzYCBwYWNrYWdlIGVjb3N5c3RlbS4gDQoNCiMjICoqT3ZlcnZpZXcqKg0KKioqDQoNCiMjIyAqKlRoZSBgdGlkeW1vZGVsc2AgZWNvc3lzdGVtKioNCioqKg0KDQpUbyBwZXJmb3JtIG91ciBhbmFseXNpcyB3ZSB3aWxsIGJlIHVzaW5nIHRoZSBgdGlkeW1vZGVsc2Agc3VpdGUgb2YgcGFja2FnZXMuIA0KWW91IG1heSBiZSBmYW1pbGlhciB3aXRoIHRoZSBvbGRlciBwYWNrYWdlcyBgY2FyZXRgIG9yIGBtbHJgIHdoaWNoIGFyZSBhbHNvIGZvciBtYWNoaW5lIGxlYXJuaW5nIGFuZCBtb2RlbGluZyBidXQgYXJlIG5vdCBhIHBhcnQgb2YgdGhlIGB0aWR5dmVyc2VgLiANCltNYXggS3Vobl0oaHR0cHM6Ly9yZXNvdXJjZXMucnN0dWRpby5jb20vYXV0aG9ycy9tYXgta3Vobil7dGFyZ2V0PSJfYmxhbmsifSBkZXNjcmliZXMgYHRpZHltb2RlbHNgIGxpa2UgdGhpczoNCg0KPiAiT3RoZXIgcGFja2FnZXMsIHN1Y2ggYXMgY2FyZXQgYW5kIG1sciwgaGVscCB0byBzb2x2ZSB0aGUgUiBtb2RlbCBBUEkgaXNzdWUuIFRoZXNlIHBhY2thZ2VzIGRvIGEgbG90IG9mIG90aGVyIHRoaW5ncyB0b286IHByZS1wcm9jZXNzaW5nLCBtb2RlbCB0dW5pbmcsIHJlc2FtcGxpbmcsIGZlYXR1cmUgc2VsZWN0aW9uLCBlbnNlbWJsaW5nLCBhbmQgc28gb24uIEluIHRoZSB0aWR5dmVyc2UsIHdlIHN0cml2ZSB0byBtYWtlIG91ciBwYWNrYWdlcyBtb2R1bGFyIGFuZCBwYXJzbmlwIGlzIGRlc2lnbmVkIG9ubHkgdG8gc29sdmUgdGhlIGludGVyZmFjZSBpc3N1ZS4gSXQgaXMgbm90IGRlc2lnbmVkIHRvIGJlIGEgZHJvcC1pbiByZXBsYWNlbWVudCBmb3IgY2FyZXQuDQpUaGUgdGlkeW1vZGVscyBwYWNrYWdlIGNvbGxlY3Rpb24sIHdoaWNoIGluY2x1ZGVzIHBhcnNuaXAsIGhhcyBvdGhlciBwYWNrYWdlcyBmb3IgbWFueSBvZiB0aGVzZSB0YXNrcywgYW5kIHRoZXkgYXJlIGRlc2lnbmVkIHRvIHdvcmsgdG9nZXRoZXIuIFdlIGFyZSB3b3JraW5nIHRvd2FyZHMgaGlnaGVyLWxldmVsIEFQSXMgdGhhdCBjYW4gcmVwbGljYXRlIGFuZCBleHRlbmQgd2hhdCB0aGUgY3VycmVudCBtb2RlbCBwYWNrYWdlcyBjYW4gZG8uIg0KDQpUaGVyZSBhcmUgbWFueSBSIHBhY2thZ2VzIGluIHRoZSBgdGlkeW1vZGVsc2AgZWNvc3lzdGVtLCB3aGljaCBhc3Npc3Qgd2l0aCB2YXJpb3VzIHN0ZXBzIGluIHRoZSBwcm9jZXNzIG9mIGJ1aWxkaW5nIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0uIFRoZXNlIGFyZSB0aGUgbWFpbiBwYWNrYWdlcywgYnV0IHRoZXJlIGFyZSBvdGhlcnMuDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInNpbXBsZXRpZHltb2RlbHMucG5nIikpDQpgYGANCg0KVGhpcyBpcyBhIHNjaGVtYXRpYyBvZiBob3cgdGhlc2UgcGFja2FnZXMgd29yayB0b2dldGhlciB0byBidWlsZCBhIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJNYWNoaW5lTGVhcm5pbmcucG5nIikpDQpgYGANCg0KIyMjICoqQmVuZWZpdHMgb2YgYHRpZHltb2RlbHNgKioNCioqKg0KDQpUaGUgdHdvIG1ham9yIGJlbmVmaXRzIG9mIGB0aWR5bW9kZWxzYCBhcmU6IA0KDQoxLiBTdGFuZGFyZGl6ZWQgd29ya2Zsb3cvZm9ybWF0L25vdGF0aW9uIGFjcm9zcyBkaWZmZXJlbnQgdHlwZXMgb2YgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG1zICANCg0KRGlmZmVyZW50IG5vdGF0aW9ucyBhcmUgcmVxdWlyZWQgZm9yIGRpZmZlcmVudCBhbGdvcml0aG1zIGFzIHRoZSBhbGdvcml0aG1zIGhhdmUgYmVlbiBkZXZlbG9wZWQgYnkgZGlmZmVyZW50IHBlb3BsZS4gVGhpcyB3b3VsZCByZXF1aXJlIHRoZSBwYWluc3Rha2luZyBwcm9jZXNzIG9mIHJlZm9ybWF0dGluZyB0aGUgZGF0YSB0byBiZSBjb21wYXRpYmxlIHdpdGggZWFjaCBhbGdvcml0aG0gaWYgbXVsdGlwbGUgYWxnb3JpdGhtcyB3ZXJlIHRlc3RlZC4NCg0KMi4gQ2FuIGVhc2lseSBtb2RpZnkgcHJlLXByb2Nlc3NpbmcsIGFsZ29yaXRobSBjaG9pY2UsIGFuZCBoeXBlci1wYXJhbWV0ZXIgdHVuaW5nIG1ha2luZyBvcHRpbWl6YXRpb24gZWFzeSAgDQoNCk1vZGlmeWluZyBhIHBpZWNlIG9mIHRoZSBvdmVyYWxsIHByb2Nlc3MgaXMgbm93IGVhc2llciB0aGFuIGJlZm9yZSBiZWNhdXNlIG1hbnkgb2YgdGhlIHN0ZXBzIGFyZSBzcGVjaWZpZWQgdXNpbmcgdGhlIGB0aWR5bW9kZWxzYCBwYWNrYWdlcyBpbiBhIGNvbnZlbmllbnQgbWFubmVyLiBUaHVzIHRoZSBlbnRpcmUgcHJvY2VzcyBjYW4gYmUgcmVydW4gYWZ0ZXIgYSBzaW1wbGUgY2hhbmdlIHRvIHByZS1wcm9jZXNzaW5nIHdpdGhvdXQgbXVjaCBkaWZmaWN1bHR5Lg0KDQoNCg0KIyMgKipTcGxpdHRpbmcgdGhlIGRhdGEqKg0KKioqDQoNClRoZSBmaXJzdCBzdGVwIGFmdGVyIGRhdGEgZXhwbG9yYXRpb24gaW4gbWFjaGluZSBsZWFybmluZyBhbmFseXNpcyBpcyB0byBbc3BsaXQgdGhlIGRhdGFdKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS90cmFpbi12YWxpZGF0aW9uLWFuZC10ZXN0LXNldHMtNzJjYjQwY2JhOWU3KXt0YXJnZXQ9Il9ibGFuayJ9IGludG8gKip0cmFpbmluZyoqIGFuZCAqKnRlc3RpbmcqKiBkYXRhIHNldHMuIA0KDQpUaGUgdHJhaW5pbmcgZGF0YSBzZXQgd2lsbCBiZSB1c2VkIHRvIGJ1aWxkIGFuZCB0dW5lIG91ciBtb2RlbC4gDQpUaGlzIGlzIHRoZSBkYXRhIHRoYXQgdGhlIG1vZGVsICJsZWFybnMiIG9uLiANClRoZSB0ZXN0aW5nIGRhdGEgc2V0IHdpbGwgYmUgdXNlZCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIG1vZGVsIGluIGEgbW9yZSBnZW5lcmFsaXphYmxlIHdheS4gV2hhdCBkbyB3ZSBtZWFuIGJ5ICJnZW5lcmFsaXphYmxlIj8NCg0KUmVtZW1iZXIgdGhhdCBvdXIgbWFpbiBnb2FsIGlzIHRvIHVzZSBvdXIgbW9kZWwgdG8gYmUgYWJsZSB0byBwcmVkaWN0IGFpciBwb2xsdXRpb24gbGV2ZWxzIGluIGFyZWFzIHdoZXJlIHRoZXJlIGFyZSBubyBncmF2aW1ldHJpYyBtb25pdG9ycy4gDQoNClRoZXJlZm9yZSwgaWYgb3VyIG1vZGVsIGlzIHJlYWxseSBnb29kIGF0IHByZWRpY3RpbmcgYWlyIHBvbGx1dGlvbiB3aXRoIHRoZSBkYXRhIHRoYXQgd2UgdXNlIHRvIGJ1aWxkIGl0LCBpdCBtaWdodCBub3QgZG8gdGhlIGJlc3Qgam9iIGZvciB0aGUgYXJlYXMgd2hlcmUgdGhlcmUgYXJlIGZldyB0byBubyBtb25pdG9ycy4gDQoNClRoaXMgd291bGQgY2F1c2UgdXMgdG8gaGF2ZSByZWFsbHkgZ29vZCBwcmVkaWN0aW9uIGFjY3VyYWN5IGFuZCB3ZSBtaWdodCBhc3N1bWUgdGhhdCB3ZSB3ZXJlIGdvaW5nIHRvIGRvIGEgZ29vZCBqb2IgZXN0aW1hdGluZyBhaXIgcG9sbHV0aW9uIGFueSB0aW1lIHdlIHVzZSBvdXIgbW9kZWwsIGJ1dCBpbiBmYWN0IHRoaXMgd291bGQgbGlrZWx5IG5vdCBiZSB0aGUgY2FzZS4gDQpUaGlzIHNpdHVhdGlvbiBpcyB3aGF0IHdlIGNhbGwgKipbb3ZlcmZpdHRpbmddKGh0dHBzOi8vdG93YXJkc2RhdGFzY2llbmNlLmNvbS90cmFpbi10ZXN0LXNwbGl0LWFuZC1jcm9zcy12YWxpZGF0aW9uLWluLXB5dGhvbi04MGI2MWJlY2E0YjYpe3RhcmdldD0iX2JsYW5rIn0gKiouDQoNCk92ZXJmaXR0aW5nIGhhcHBlbnMgd2hlbiB3ZSBlbmQgdXAgbW9kZWxpbmcgbm90IG9ubHkgdGhlIG1ham9yIHJlbGF0aW9uc2hpcHMgaW4gb3VyIGRhdGEgYnV0IGFsc28gdGhlIG5vaXNlIHdpdGhpbiBvdXIgZGF0YS4gDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vbWlyby5tZWRpdW0uY29tL21heC8xMTEwLzEqdEJFclhZVnZUdzJqU1VZSzd0aFUyQS5wbmciKQ0KYGBgDQoNCiMjIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vbWF4LzExMTAvMSp0QkVyWFlWdlR3MmpTVVlLN3RoVTJBLnBuZyl7dGFyZ2V0PSJfYmxhbmsifQ0KDQpJZiB3ZSBnZXQgZ29vZCBwcmVkaWN0aW9uIHdpdGggb3VyIHRlc3Rpbmcgc2V0LCB0aGVuIHdlIGtub3cgdGhhdCBvdXIgbW9kZWwgY2FuIGJlIGFwcGxpZWQgdG8gb3RoZXIgZGF0YSBhbmQgd2lsbCBsaWtlbHkgcGVyZm9ybSB3ZWxsLiBXZSB3aWxsIGRpc2N1c3MgdGhpcyBtb3JlIGxhdGVyLg0KDQpXZSB3aWxsIG5vdCB0b3VjaCB0aGUgdGVzdGluZyBzZXQgdW50aWwgd2UgaGF2ZSBjb21wbGV0ZWQgb3B0aW1pemluZyBvdXIgbW9kZWwgd2l0aCB0aGUgdHJhaW5pbmcgc2V0LiANClRoaXMgd2lsbCBhbGxvdyB1cyB0byBoYXZlIGEgbGVzcyBiaWFzZWQgZXZhbHVhdGlvbiBvZiBob3cgd2VsbCBvdXIgbW9kZWwgY2FuIGRvIHdpdGggb3RoZXIgZGF0YSBiZXNpZGVzIHRoZSBkYXRhIHVzZWQgaW4gdGhlIHRyYWluaW5nIHNldCB0byBidWlsZCB0aGUgbW9kZWwuIA0KSWRlYWxseSwgeW91IHdvdWxkIGFsc28gd2FudCBhIGNvbXBsZXRlbHkgaW5kZXBlbmRlbnQgZGF0YSBzZXQgdG8gZnVydGhlciB0ZXN0IHRoZSBwZXJmb3JtYW5jZSBvZiB5b3VyIG1vZGVsLg0KDQpUbyBzcGxpdCB0aGUgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nLCB3ZSB3aWxsIHVzZSB0aGUgYGluaXRpYWxfc3BsaXQoKWAgZnVuY3Rpb24gaW4gdGhlIGByc2FtcGxlYCBwYWNrYWdlIHRvIHNwZWNpZnkgaG93IHdlIHdhbnQgdG8gc3BsaXQgb3VyIGRhdGEuDQoNCg0KYGBge3IsIGVjaG89RkFMU0V9DQoNCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInNwbGl0LnBuZyIpKQ0KYGBgDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzNCkNCnBtX3NwbGl0IDwtIHJzYW1wbGU6OmluaXRpYWxfc3BsaXQoZGF0YSA9IHBtLCBwcm9wID0gMi8zKQ0KcG1fc3BsaXQNCmBgYA0KDQpBIGNvdXBsZSBvZiBub3RlcyBmcm9tIHRoZSBjb2RlIGFib3ZlOiANCg0KLSBUeXBpY2FsbHksIGRhdGEgYXJlIHNwbGl0IGludG8gMy80IG9mIHRoZSBvYnNlcnZhdGlvbnMgZm9yIHRyYWluaW5nIGFuZCAxLzQgZm9yIHRlc3RpbmcuIFRoaXMgaXMgdGhlIGRlZmF1bHQgcHJvcG9ydGlvbiBhbmQgZG9lcyBub3QgbmVlZCB0byBiZSBzcGVjaWZpZWQuIEhvd2V2ZXIsIHlvdSBjYW4gY2hhbmdlIHRoZSBwcm9wb3J0aW9uIHVzaW5nIHRoZSBgcHJvcGAgYXJndW1lbnQsIHdoaWNoIHdlIHdpbGwgZG8gdGhhdCBoZXJlIGZvciBpbGx1c3RyYXRpdmUgcHVycG9zZXMuDQotIFNpbmNlIHRoZSBzcGxpdCBpcyBwZXJmb3JtZWQgcmFuZG9tbHksIGl0IGlzIGEgZ29vZCBpZGVhIHRvIHVzZSB0aGUgYHNldC5zZWVkKClgIGZ1bmN0aW9uIGluIGJhc2UgUiB0byBlbnN1cmUgdGhhdCBpZiB5b3VyIHJlcnVuIHlvdXIgY29kZSB0aGF0IHlvdXIgc3BsaXQgd2lsbCBiZSB0aGUgc2FtZSBuZXh0IHRpbWUuDQotIFdlIGNhbiBzZWUgdGhlIG51bWJlciBvZiBtb25pdG9ycyBpbiBvdXIgdHJhaW5pbmcsIHRlc3RpbmcsIGFuZCBvcmlnaW5hbCBkYXRhIGJ5IHR5cGluZyBpbiB0aGUgbmFtZSBvZiBvdXIgc3BsaXQgb2JqZWN0LiBUaGUgcmVzdWx0IHdpbGwgbG9vayBsaWtlIHRoaXM6DQo8dHJhaW5pbmcgZGF0YSBzYW1wbGUgbnVtYmVyLCB0ZXN0aW5nIGRhdGEgc2FtcGxlIG51bWJlciwgb3JpZ2luYWwgc2FtcGxlIG51bWJlcj4gDQoNCk5vdywgeW91IGNhbiBhbHNvIHNwZWNpZnkgYSB2YXJpYWJsZSB0byBzdHJhdGlmeSBieSB3aXRoIHRoZSBgc3RyYXRhYCBhcmd1bWVudC4gDQpUaGlzIGlzIHVzZWZ1bCBpZiB5b3UgaGF2ZSBpbWJhbGFuY2VkIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhbmQgeW91IHdvdWxkIGxpa2UgdG8gaW50ZW50aW9uYWxseSBtYWtlIHN1cmUgdGhhdCB0aGVyZSBhcmUgc2ltaWxhciBudW1iZXIgb2Ygc2FtcGxlcyBvZiB0aGUgcmFyZXIgY2F0ZWdvcmllcyBpbiBib3RoIHRoZSB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXRzLiANCk90aGVyd2lzZSB0aGUgc3BsaXQgaXMgcGVyZm9ybWVkIHJhbmRvbWx5LiANCg0KQWNjb3JkaW5nIHRvIHRoZSBbZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3JzYW1wbGUvdmVyc2lvbnMvMC4wLjUvdG9waWNzL2luaXRpYWxfc3BsaXQpIGZvciB0aGUgYHJzYW1wbGVgIHBhY2thZ2U6DQoNCj4gVGhlIHN0cmF0YSBhcmd1bWVudCBjYXVzZXMgdGhlIHJhbmRvbSBzYW1wbGluZyB0byBiZSBjb25kdWN0ZWQgd2l0aGluIHRoZSBzdHJhdGlmaWNhdGlvbiB2YXJpYWJsZS4gVGhpcyBjYW4gaGVscCBlbnN1cmUgdGhhdCB0aGUgbnVtYmVyIG9mIGRhdGEgcG9pbnRzIGluIHRoZSB0cmFpbmluZyBkYXRhIGlzIGVxdWl2YWxlbnQgdG8gdGhlIHByb3BvcnRpb25zIGluIHRoZSBvcmlnaW5hbCBkYXRhIHNldC4NCg0KSW4gdGhlIGNhc2Ugd2l0aCBvdXIgZGF0YSBzZXQsIHBlcmhhcHMgd2Ugd291bGQgbGlrZSBvdXIgdHJhaW5pbmcgc2V0IHRvIGhhdmUgc2ltaWxhciBwcm9wb3J0aW9ucyBvZiBtb25pdG9ycyBmcm9tIGVhY2ggb2YgdGhlIHN0YXRlcyBhcyBpbiB0aGUgaW5pdGlhbCBkYXRhLiANClRoaXMgbWlnaHQgYmUgdXNlZnVsIGlmIHdlIHdhbnQgb3VyIG1vZGVsIHRvIGJlIGdlbmVyYWxpemFibGUgYWNyb3NzIGFsbCBvZiB0aGUgc3RhdGVzLg0KDQpXZSBjYW4gc2VlIHRoYXQgaW5kZWVkIHRoZXJlIGFyZSBkaWZmZXJlbnQgcHJvcG9ydGlvbnMgb2YgbW9uaXRvcnMgaW4gZWFjaCBzdGF0ZSBieSB1c2luZyB0aGUgYGNvdW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIA0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFfQ0KY291bnQocG0sIHN0YXRlKQ0KYGBgDQoNClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6DQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCg0KYGBge3IsIGVjaG89RkFMU0V9DQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhDQpjb3VudChwbSwgc3RhdGUpICU+JQ0KICBwcmludChuID0gMWUzKQ0KYGBgDQojIyMjDQoNCklmIG91ciBkYXRhIHNldCB3ZXJlIGxhcmdlIGVub3VnaCBpdCBtaWdodCBiZSBuaWNlIHRoZW4gdG8gc3RyYXRpZnkgYnkgc3RhdGUgdXNpbmcgdGhlIGBzdHJhdGEgPSAic3RhdGUiYCBhcmd1bWVudCBpbiBgaW5pdGlhbF9zcGxpdCgpYCwgYnV0IG91ciBkYXRhIGlzIHVuZm9ydHVuYXRlbHkgbm90IGxhcmdlIGVub3VnaC4gDQoNCkltcG9ydGFudGx5IHRoZSBgaW5pdGlhbF9zcGxpdCgpYCBmdW5jdGlvbiBvbmx5IGRldGVybWluZXMgd2hhdCByb3dzIG9mIG91ciBgcG1gIGRhdGEgZnJhbWUgc2hvdWxkIGJlIGFzc2lnbmVkIGZvciB0cmFpbmluZyBvciB0ZXN0aW5nLCBpdCBkb2VzIG5vdCBhY3R1YWxseSBzcGxpdCB0aGUgZGF0YS4gDQoNClRvIGV4dHJhY3QgdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIGRhdGEgd2UgY2FuIHVzZSB0aGUgYHRyYWluaW5nKClgIGFuZCBgdGVzdGluZygpYCBmdW5jdGlvbnMgYWxzbyBvZiB0aGUgYHJzYW1wbGVgIHBhY2thZ2UuDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCmBgYHtyfQ0KdHJhaW5fcG0gPC1yc2FtcGxlOjp0cmFpbmluZyhwbV9zcGxpdCkNCnRlc3RfcG0gPC1yc2FtcGxlOjp0ZXN0aW5nKHBtX3NwbGl0KQ0KIA0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KY291bnQodHJhaW5fcG0sIHN0YXRlKQ0KY291bnQodGVzdF9wbSwgc3RhdGUpDQpgYGANCiMjIyMNCg0KDQoNCiMjICoqUHJlcGFyaW5nIGZvciBwcmUtcHJvY2Vzc2luZyB0aGUgZGF0YSoqDQoqKioNCg0KQWZ0ZXIgc3BsaXR0aW5nIHRoZSBkYXRhLCB0aGUgbmV4dCBzdGVwIGlzIHRvIHByb2Nlc3MgdGhlIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEgc28gdGhhdCB0aGUgZGF0YSBhcmUgYXJlIGNvbXBhdGlibGUgYW5kIG9wdGltaXplZCB0byBiZSB1c2VkIHdpdGggdGhlIG1vZGVsLiANClRoaXMgaW52b2x2ZXMgYXNzaWduaW5nIHZhcmlhYmxlcyB0byBzcGVjaWZpYyByb2xlcyB3aXRoaW4gdGhlIG1vZGVsIGFuZCBwcmUtcHJvY2Vzc2luZyBsaWtlIHNjYWxpbmcgdmFyaWFibGVzIGFuZCByZW1vdmluZyByZWR1bmRhbnQgdmFyaWFibGVzLiANClRoaXMgcHJvY2VzcyBpcyBhbHNvIGNhbGxlZCBmZWF0dXJlIGVuZ2luZWVyaW5nLg0KDQpUbyBkbyB0aGlzIGluIGB0aWR5bW9kZWxzYCwgd2Ugd2lsbCBjcmVhdGUgd2hhdCdzIGNhbGxlZCBhICJyZWNpcGUiIHVzaW5nIHRoZSBgcmVjaXBlc2AgcGFja2FnZSwgd2hpY2ggaXMgYSBzdGFuZGFyZGl6ZWQgZm9ybWF0IGZvciBhIHNlcXVlbmNlIG9mIHN0ZXBzIGZvciBwcmUtcHJvY2Vzc2luZyB0aGUgZGF0YS4NClRoaXMgY2FuIGJlIHZlcnkgdXNlZnVsIGJlY2F1c2UgaXQgbWFrZXMgdGVzdGluZyBvdXQgZGlmZmVyZW50IHByZS1wcm9jZXNzaW5nIHN0ZXBzIG9yIGRpZmZlcmVudCBhbGdvcml0aG1zIHdpdGggdGhlIHNhbWUgcHJlLXByb2Nlc3NpbmcgdmVyeSBlYXN5IGFuZCByZXByb2R1Y2libGUuDQpDcmVhdGluZyBhIHJlY2lwZSBzcGVjaWZpZXMgKipob3cgYSBkYXRhIGZyYW1lIG9mIHByZWRpY3RvcnMgc2hvdWxkIGJlIGNyZWF0ZWQqKiAtIGl0IHNwZWNpZmllcyB3aGF0IHZhcmlhYmxlcyB0byBiZSB1c2VkIGFuZCB0aGUgcHJlLXByb2Nlc3Npbmcgc3RlcHMsIGJ1dCBpdCAqKmRvZXMgbm90IGV4ZWN1dGUgdGhlc2Ugc3RlcHMqKiBvciBjcmVhdGUgdGhlIGRhdGEgZnJhbWUgb2YgcHJlZGljdG9ycy4NCg0KIyMjIFN0ZXAgMTogU3BlY2lmeSB2YXJpYWJsZXMgcm9sZXMgd2l0aCBgcmVjaXBlKClgIGZ1bmN0aW9uDQoNClRoZSBmaXJzdCB0aGluZyB0byBkbyB0byBjcmVhdGUgYSByZWNpcGUgaXMgdG8gc3BlY2lmeSB3aGljaCB2YXJpYWJsZXMgd2Ugd2lsbCBiZSB1c2luZyBhcyBvdXIgb3V0Y29tZSBhbmQgcHJlZGljdG9ycyB1c2luZyB0aGUgYHJlY2lwZSgpYCBmdW5jdGlvbi4gDQpJbiB0ZXJtcyBvZiB0aGUgbWV0YXBob3Igb2YgYmFraW5nLCB3ZSBjYW4gdGhpbmsgb2YgdGhpcyBhcyBsaXN0aW5nIG91ciBpbmdyZWRpZW50cy4gDQpUcmFuc2xhdGluZyB0aGlzIHRvIHRoZSBgcmVjaXBlc2AgcGFja2FnZSwgd2UgdXNlIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uIHRvIGFzc2lnbiByb2xlcyB0byBhbGwgdGhlIHZhcmlhYmxlcy4gDQoNCkxldCdzIHRyeSB0aGUgc2ltcGxlc3QgcmVjaXBlIHdpdGggbm8gcHJlLXByb2Nlc3Npbmcgc3RlcHM6IHNpbXBseSBsaXN0IHRoZSBvdXRjb21lIGFuZCBwcmVkaWN0b3IgdmFyaWFibGVzLg0KDQpXZSBjYW4gZG8gc28gaW4gdHdvIHdheXM6ICANCg0KMSkgVXNpbmcgZm9ybXVsYSBub3RhdGlvbiAgDQoyKSBBc3NpZ25pbmcgcm9sZXMgdG8gZWFjaCB2YXJpYWJsZSAgDQoNCkxldCdzIGxvb2sgYXQgdGhlIGZpcnN0IHdheSB1c2luZyBmb3JtdWxhIG5vdGF0aW9uLCB3aGljaCBsb29rcyBsaWtlIHRoaXM6ICANCg0Kb3V0Y29tZShzKSB+IHByZWRpY3RvcihzKSAgDQoNCklmIGluIHRoZSBjYXNlIG9mIG11bHRpcGxlIHByZWRpY3RvcnMgb3IgYSBtdWx0aXZhcmlhdGUgc2l0dWF0aW9uIHdpdGggdHdvIG91dGNvbWVzLCB1c2UgYSBwbHVzIHNpZ246ICANCg0Kb3V0Y29tZTEgKyBvdXRjb21lMiB+IHByZWRpY3RvcjEgKyBwcmVkaWN0b3IyICANCg0KSWYgd2Ugd2FudCB0byBpbmNsdWRlIGFsbCBwcmVkaWN0b3JzIHdlIGNhbiB1c2UgYSBwZXJpb2QgbGlrZSBzbzogIA0KDQpvdXRjb21lX3ZhcmlhYmxlX25hbWUgfiAuICANCg0KTm93IHdpdGggb3VyIGRhdGEsIHdlIHdpbGwgc3RhcnQgYnkgbWFraW5nIGEgcmVjaXBlIGZvciBvdXIgdHJhaW5pbmcgZGF0YS4NCklmIHlvdSByZWNhbGwsIHRoZSBjb250aW51b3VzIG91dGNvbWUgdmFyaWFibGUgaXMgYHZhbHVlYCAodGhlIGF2ZXJhZ2UgYW5udWFsIGdyYXZpbWV0cmljIG1vbml0b3IgUE1+Mi41fiBjb25jZW50cmF0aW9uIGluIHVnL21eM14pLiANCk91ciBmZWF0dXJlcyAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgYXJlIGFsbCB0aGUgb3RoZXIgdmFyaWFibGVzIGV4Y2VwdCB0aGUgbW9uaXRvciBJRCwgd2hpY2ggaXMgYW4gYGlkYCB2YXJpYWJsZS4NCg0KVGhlIHJlYXNvbiBub3QgdG8gaW5jbHVkZSB0aGUgYGlkYCB2YXJpYWJsZSBpcyBiZWNhdXNlIHRoaXMgdmFyaWFibGUgaW5jbHVkZXMgdGhlIGNvdW50eSBudW1iZXIgYW5kIGEgbnVtYmVyIGRlc2lnbmF0aW5nIHdoaWNoIHBhcnRpY3VsYXIgbW9uaXRvciB0aGUgdmFsdWVzIGNhbWUgZnJvbSAob2YgdGhlIG1vbml0b3JzIHRoZXJlIGFyZSBpbiB0aGF0IGNvdW50eSkuIA0KU2luY2UgdGhpcyBudW1iZXIgaXMgYXJiaXRyYXJ5IGFuZCB0aGUgY291bnR5IGluZm9ybWF0aW9uIGlzIGFsc28gZ2l2ZW4gaW4gdGhlIGRhdGEsIGFuZCB0aGUgZmFjdCB0aGF0IGVhY2ggbW9uaXRvciBvbmx5IGhhcyBvbmUgdmFsdWUgaW4gdGhlIGB2YWx1ZWAgdmFyaWFibGUsIG5vdGhpbmcgaXMgZ2FpbmVkIGJ5IGluY2x1ZGluZyB0aGlzIHZhcmlhYmxlIGFuZCBpdCBtYXkgaW5zdGVhZCBpbnRyb2R1Y2Ugbm9pc2UuIA0KSG93ZXZlciwgaXQgaXMgdXNlZnVsIHRvIGtlZXAgdGhpcyBkYXRhIHRvIHRha2UgYSBsb29rIGF0IHdoYXQgaXMgaGFwcGVuaW5nIGxhdGVyLiANCldlIHdpbGwgc2hvdyB5b3Ugd2hhdCB0byBkbyBpbiB0aGlzIGNhc2UgaW4ganVzdCBhIGJpdC4NCg0KSW4gdGhlIHNpbXBsZXN0IGNhc2UsIHdlIG1pZ2h0IHVzZSBhbGwgcHJlZGljdG9ycyBsaWtlIHRoaXM6DQoNCmBgYHtyfQ0Kc2ltcGxlX3JlYyA8LSB0cmFpbl9wbSAlPiUNCiAgcmVjaXBlczo6cmVjaXBlKHZhbHVlIH4gLikNCg0Kc2ltcGxlX3JlYw0KYGBgDQoNCldlIHNlZSBhIHJlY2lwZSBoYXMgYmVlbiBjcmVhdGVkIHdpdGggMSBvdXRjb21lIHZhcmlhYmxlIGFuZCA0OSBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykuIA0KQWxzbywgbm90aWNlIGhvdyB3ZSBuYW1lZCB0aGUgb3V0cHV0IG9mIGByZWNpcGUoKWAuIA0KVGhlIG5hbWluZyBjb252ZW50aW9uIGZvciByZWNpcGUgb2JqZWN0cyBpcyBgKl9yZWNgIG9yIGByZWNgLiANCg0KTm93LCBsZXQncyBnZXQgYmFjayB0byB0aGUgYGlkYCB2YXJpYWJsZS4gDQpJbnN0ZWFkIG9mIGluY2x1ZGluZyBpdCBhcyBhIHByZWRpY3RvciB2YXJpYWJsZSwgd2UgY291bGQgYWxzbyB1c2UgdGhlIGB1cGRhdGVfcm9sZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuDQoNCmBgYHtyfQ0Kc2ltcGxlX3JlYyA8LSB0cmFpbl9wbSAlPiUNCiAgcmVjaXBlczo6cmVjaXBlKHZhbHVlIH4gLikgJT4lDQogIHJlY2lwZXM6OnVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpDQoNCnNpbXBsZV9yZWMNCmBgYA0KDQo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSBsZWFybiBtb3JlIGFib3V0IHRoZSB3b3JraW5nIHdpdGggYGlkYCB2YXJpYWJsZXMgPC9zdW1tYXJ5Pg0KDQpUaGlzIG9wdGlvbiB3b3JrcyB3ZWxsIHdpdGggdGhlIG5ld2VyIGB3b3JrZmxvd3NgIHBhY2thZ2UsIGhvd2V2ZXIgYGlkYCB2YXJpYWJsZXMgYXJlIG9mdGVuIGRyb3BwZWQgZnJvbSBhbmFseXNlcyB0aGF0IGRvIG5vdCB1c2UgdGhpcyBuZXdlciBwYWNrYWdlIGFzIHRoZXkgY2FuIG1ha2UgdGhlIHByb2Nlc3MgZGlmZmljdWx0IHdpdGggdXNpbmcgdGhlIGBwYXJzbmlwYCBwYWNrYWdlIGFsb25lIGR1ZSB0byB0aGUgZmFjdCB0aGF0IG5ldyBsZXZlbHMgKG9yIHBvc3NpYmxlIHZhbHVlcykgbWF5IGJlIGludHJvZHVjZWQgd2l0aCB0aGUgdGVzdGluZyBkYXRhLg0KDQo8L2RldGFpbHM+DQoNCldlIGNvdWxkIGFsc28gc3BlY2lmeSB0aGUgb3V0Y29tZSBhbmQgcHJlZGljdG9ycyBpbiB0aGUgc2FtZSB3YXkgYXMgd2UganVzdCBzcGVjaWZpZWQgdGhlIGlkIHZhcmlhYmxlLiANClBsZWFzZSBzZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvcmVjaXBlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIGV4YW1wbGVzIG9mIG90aGVyIHJvbGVzIGZvciB2YXJpYWJsZXMuIA0KVGhlIHJvbGUgY2FuIGJlIGFjdHVhbGx5IGJlIGFueSB2YWx1ZS4gDQoNClRoZSBvcmRlciBpcyBpbXBvcnRhbnQgaGVyZSwgYXMgd2UgZmlyc3QgbWFrZSBhbGwgdmFyaWFibGVzIHByZWRpY3RvcnMgYW5kIHRoZW4gb3ZlcnJpZGUgdGhpcyByb2xlIGZvciB0aGUgb3V0Y29tZSBhbmQgYGlkYCB2YXJpYWJsZS4gDQpXZSB3aWxsIHVzZSB0aGUgYGV2ZXJ5dGhpbmcoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byBzdGFydCB3aXRoIGFsbCBvZiB0aGUgdmFyaWFibGVzIGluIGB0cmFpbl9wbWAuDQoNCmBgYHtyfQ0Kc2ltcGxlX3JlYyA8LXJlY2lwZSh0cmFpbl9wbSkgJT4lDQogICAgdXBkYXRlX3JvbGUoZXZlcnl0aGluZygpLCBuZXdfcm9sZSA9ICJwcmVkaWN0b3IiKSU+JQ0KICAgIHVwZGF0ZV9yb2xlKHZhbHVlLCBuZXdfcm9sZSA9ICJvdXRjb21lIiklPiUNCiAgICB1cGRhdGVfcm9sZShpZCwgbmV3X3JvbGUgPSAiaWQgdmFyaWFibGUiKQ0KDQpzaW1wbGVfcmVjDQpgYGANCg0KV2UgY2FuIHZpZXcgb3VyIHJlY2lwZSBpbiBtb3JlIGRldGFpbCB1c2luZyB0aGUgYmFzZSBgc3VtbWFyeSgpYCBmdW5jdGlvbi4NCg0KYGBge3J9DQpzdW1tYXJ5KHNpbXBsZV9yZWMpDQpgYGANCg0KVG8gc3VtbWFyaXplIHRoaXMgc3RlcCwgd2UgdXNlIHRoZSBgcmVjaXBlKClgIGZ1bmN0aW9uIHRvIGFzc2lnbiByb2xlcyB0byBhbGwgdGhlIHZhcmlhYmxlczogDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjQwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIlN0YXJ0aW5nX2FfcmVjaXBlX3JlY2lwZXMxLnBuZyIpKQ0KYGBgDQoNCg0KIyMjIFN0ZXAgMjogU3BlY2lmeSB0aGUgcHJlLXByb2Nlc3Npbmcgc3RlcHMgd2l0aCBgc3RlcCooKWAgZnVuY3Rpb25zDQoNCk5leHQsIHdlIHVzZSB0aGUgYHN0ZXAqKClgIGZ1bmN0aW9ucyBmcm9tIHRoZSBgcmVjaXBlYCBwYWNrYWdlIHRvIHNwZWNpZnkgcHJlLXByb2Nlc3Npbmcgc3RlcHMuIA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJNYWtpbmdfYV9yZWNpcGVfcmVjaXBlczIucG5nIikpDQpgYGANCg0KKipUaGlzIFtsaW5rXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3JlY2lwZXMvcmVmZXJlbmNlL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gYW5kIHRoaXMgW2xpbmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZWNpcGVzL3JlY2lwZXMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHNob3cgdGhlIG1hbnkgb3B0aW9ucyBmb3IgcmVjaXBlIHN0ZXAgZnVuY3Rpb25zLioqDQoNCjx1PlRoZXJlIGFyZSBzdGVwIGZ1bmN0aW9ucyBmb3IgYSB2YXJpZXR5IG9mIHB1cnBvc2VzOjwvdT4NCg0KMS4gWyoqSW1wdXRhdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JbXB1dGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBmaWxsaW5nIGluIG1pc3NpbmcgdmFsdWVzIGJhc2VkIG9uIHRoZSBleGlzdGluZyBkYXRhIA0KMi4gWyoqVHJhbnNmb3JtYXRpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGF0YV90cmFuc2Zvcm1hdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gLS0gY2hhbmdpbmcgYWxsIHZhbHVlcyBvZiBhIHZhcmlhYmxlIGluIHRoZSBzYW1lIHdheSwgdHlwaWNhbGx5IHRvIG1ha2UgaXQgbW9yZSBub3JtYWwgb3IgZWFzaWVyIHRvIGludGVycHJldA0KMy4gWyoqRGlzY3JldGl6YXRpb24qKl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGlzY3JldGl6YXRpb25fb2ZfY29udGludW91c19mZWF0dXJlcyl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjb252ZXJ0aW5nIGNvbnRpbnVvdXMgdmFsdWVzIGludG8gZGlzY3JldGUgb3Igbm9taW5hbCB2YWx1ZXMgLSBiaW5uaW5nIGZvciBleGFtcGxlIHRvIHJlZHVjZSB0aGUgbnVtYmVyIG9mIHBvc3NpYmxlIGxldmVscyAoSG93ZXZlciB0aGlzIGlzIGdlbmVyYWxseSBub3QgYWR2aXNhYmxlISkNCjQuIFsqKkVuY29kaW5nIC8gQ3JlYXRpbmcgRHVtbXkgVmFyaWFibGVzKipdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0R1bW15X3ZhcmlhYmxlXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjcmVhdGluZyBhIG51bWVyaWMgY29kZSBmb3IgY2F0ZWdvcmljYWwgdmFyaWFibGVzDQooWyoqTW9yZSBvbiBEdW1teSBWYXJpYWJsZXMgYW5kIG9uZSBob3QgZW5jb2RpbmcqKl0oaHR0cHM6Ly9tZWRpdW0uY29tL3AvYjU4NDBiZTNjNDFhL3Jlc3BvbnNlcy9zaG93KXt0YXJnZXQ9Il9ibGFuayJ9KQ0KNS4gWyoqRGF0YSB0eXBlIGNvbnZlcnNpb25zKipdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9oYWJsYXIvdmlnbmV0dGVzL2NvbnZlcnQuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgLS0gd2hpY2ggbWVhbnMgY2hhbmdpbmcgZnJvbSBpbnRlZ2VyIHRvIGZhY3RvciBvciBudW1lcmljIHRvIGRhdGUgZXRjLg0KNi4gWyoqSW50ZXJhY3Rpb24qKl0oaHR0cHM6Ly9zdGF0aXN0aWNzYnlqaW0uY29tL3JlZ3Jlc3Npb24vaW50ZXJhY3Rpb24tZWZmZWN0cy8pe3RhcmdldD0iX2JsYW5rIn0gIHRlcm0gYWRkaXRpb24gdG8gdGhlIG1vZGVsIC0tIHdoaWNoIG1lYW5zIHRoYXQgd2Ugd291bGQgYmUgbW9kZWxpbmcgZm9yIHByZWRpY3RvcnMgdGhhdCB3b3VsZCBpbmZsdWVuY2UgdGhlIGNhcGFjaXR5IG9mIGVhY2ggb3RoZXIgdG8gcHJlZGljdCB0aGUgb3V0Y29tZQ0KNy4gWyoqTm9ybWFsaXphdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ob3JtYWxpemF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAtLSBjZW50ZXJpbmcgYW5kIHNjYWxpbmcgdGhlIGRhdGEgdG8gYSBzaW1pbGFyIHJhbmdlIG9mIHZhbHVlcw0KOC4gWyoqRGltZW5zaW9uYWxpdHkgUmVkdWN0aW9uLyBTaWduYWwgRXh0cmFjdGlvbioqXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaW1lbnNpb25hbGl0eV9yZWR1Y3Rpb24pe3RhcmdldD0iX2JsYW5rIn0gLS0gcmVkdWNpbmcgdGhlIHNwYWNlIG9mIGZlYXR1cmVzIG9yIHByZWRpY3RvcnMgdG8gYSBzbWFsbGVyIHNldCBvZiB2YXJpYWJsZXMgdGhhdCBjYXB0dXJlIHRoZSB2YXJpYXRpb24gb3Igc2lnbmFsIGluIHRoZSBvcmlnaW5hbCB2YXJpYWJsZXMgKGV4LiBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIGFuZCBJbmRlcGVuZGVudCBDb21wb25lbnQgQW5hbHlzaXMpDQo5LiAqKkZpbHRlcmluZyoqIC0tIGZpbHRlcmluZyBvcHRpb25zIGZvciByZW1vdmluZyB2YXJpYWJsZXMgKGV4LiByZW1vdmUgdmFyaWFibGVzIHRoYXQgYXJlIGhpZ2hseSBjb3JyZWxhdGVkIHRvIG90aGVycyBvciByZW1vdmUgdmFyaWFibGVzIHdpdGggdmVyeSBsaXR0bGUgdmFyaWFuY2UgYW5kIHRoZXJlZm9yZSBsaWtlbHkgbGl0dGxlIHByZWRpY3RpdmUgY2FwYWNpdHkpDQoxMC4gWyoqUm93IG9wZXJhdGlvbnMqKl0oaHR0cHM6Ly90YXJ0YXJ1cy5vcmcvZ2FyZXRoL21hdGhzL0xpbmVhcl9BbGdlYnJhL3Jvd19vcGVyYXRpb25zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAtLSBwZXJmb3JtaW5nIGZ1bmN0aW9ucyBvbiB0aGUgdmFsdWVzIHdpdGhpbiB0aGUgcm93cyAgKGV4LiByZWFycmFuZ2luZywgZmlsdGVyaW5nLCBpbXB1dGluZykNCjExLiAqKkNoZWNraW5nIGZ1bmN0aW9ucyoqIC0tIFNhbml0eSBjaGVja3MgdG8gbG9vayBmb3IgbWlzc2luZyB2YWx1ZXMsIHRvIGxvb2sgYXQgdGhlIHZhcmlhYmxlIGNsYXNzZXMgZXRjLg0KDQpBbGwgb2YgdGhlIHN0ZXAgZnVuY3Rpb25zIGxvb2sgbGlrZSBgc3RlcF8qKClgIHdpdGggdGhlIGAqYCByZXBsYWNlZCB3aXRoIGEgbmFtZSwgZXhjZXB0IGZvciB0aGUgY2hlY2sgZnVuY3Rpb25zIHdoaWNoIGxvb2sgbGlrZSBgY2hlY2tfKigpYC4NCg0KVGhlcmUgYXJlIHNldmVyYWwgd2F5cyB0byBzZWxlY3Qgd2hhdCB2YXJpYWJsZXMgdG8gYXBwbHkgc3RlcHMgdG86ICANCg0KMS4gVXNpbmcgYHRpZHlzZWxlY3RgIG1ldGhvZHM6IGBjb250YWlucygpYCwgYG1hdGNoZXMoKWAsIGBzdGFydHNfd2l0aCgpYCwgYGVuZHNfd2l0aCgpYCwgYGV2ZXJ5dGhpbmcoKWAsIGBudW1fcmFuZ2UoKWAgIA0KMi4gVXNpbmcgdGhlIHR5cGU6IGBhbGxfbm9taW5hbCgpYCwgYGFsbF9udW1lcmljKClgICwgYGhhc190eXBlKClgIA0KMy4gVXNpbmcgdGhlIHJvbGU6IGBhbGxfcHJlZGljdG9ycygpYCwgYGFsbF9vdXRjb21lcygpYCwgYGhhc19yb2xlKClgDQo0LiBVc2luZyB0aGUgbmFtZSAtIHVzZSB0aGUgYWN0dWFsIG5hbWUgb2YgdGhlIHZhcmlhYmxlL3ZhcmlhYmxlcyBvZiBpbnRlcmVzdCAgDQoNCkxldCdzIHRyeSBhZGRpbmcgc29tZSBzdGVwcyB0byBvdXIgcmVjaXBlLg0KDQoNCldlIG1pZ2h0IHdhbnQgdG8gcG90ZW50aWFsbHkgW29uZSBob3QgZW5jb2RlXShodHRwczovL21hY2hpbmVsZWFybmluZ21hc3RlcnkuY29tL3doeS1vbmUtaG90LWVuY29kZS1kYXRhLWluLW1hY2hpbmUtbGVhcm5pbmcvKXt0YXJnZXQ9Il9ibGFuayJ9IHNvbWUgb2Ygb3VyIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBzbyB0aGF0IHRoZXkgY2FuIGJlIHVzZWQgd2l0aCBjZXJ0YWluIGFsZ29yaXRobXMuIA0KDQpXZSBjYW4gZG8gdGhpcyB3aXRoIHRoZSBgc3RlcF9kdW1teSgpYCBmdW5jdGlvbiBhbmQgdGhlIGBvbmVfaG90ID0gVFJVRWAgYXJndW1lbnQuIA0KT25lIGhvdCBlbmNvZGluZyBtZWFucyB0aGF0IHdlIGRvIG5vdCBzaW1wbHkgZW5jb2RlIG91ciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgbnVtZXJpY2FsbHksIGFzIG91ciBudW1lcmljIGFzc2lnbm1lbnRzIGNhbiBiZSBpbnRlcnByZXRlZCBieSBhbGdvcml0aG1zIGFzIGhhdmluZyBhIHBhcnRpY3VsYXIgcmFuayBvciBvcmRlci4gDQpJbnN0ZWFkLCBiaW5hcnkgdmFyaWFibGVzIG1hZGUgb2YgMXMgYW5kIDBzIGFyZSB1c2VkIHRvIGFyYml0cmFyaWx5IGFzc2lnbiBhIG51bWVyaWMgdmFsdWUgdGhhdCBoYXMgbm8gYXBwYXJlbnQgb3JkZXIuDQoNCmBgYHtyfQ0Kc2ltcGxlX3JlYyAlPiUNCiAgc3RlcF9kdW1teShzdGF0ZSwgY291bnR5LCBjaXR5LCB6Y3RhLCBvbmVfaG90ID0gVFJVRSkNCmBgYA0KDQpPdXIgYGZpcHNgIHZhcmlhYmxlIGluY2x1ZGVzIGEgbnVtZXJpYyBjb2RlIGZvciBzdGF0ZSBhbmQgY291bnR5IC0gYW5kIHRoZXJlZm9yZSBpcyBlc3NlbnRpYWxseSBhIHByb3h5IGZvciBjb3VudHkuDQpTaW5jZSB3ZSBhbHJlYWR5IGhhdmUgY291bnR5LCB3ZSB3aWxsIGp1c3QgdXNlIGl0IGFuZCBrZWVwIHRoZSBgZmlwc2AgSUQgYXMgYW5vdGhlciBJRCB2YXJpYWJsZS4NCg0KV2UgY2FuIHJlbW92ZSB0aGUgYGZpcHNgIHZhcmlhYmxlIGZyb20gdGhlIHByZWRpY3RvcnMgdXNpbmcgYHVwZGF0ZV9yb2xlKClgIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSByb2xlIGlzIG5vIGxvbmdlciBgInByZWRpY3RvciJgLiANCldlIGNhbiBtYWtlIHRoZSByb2xlIGFueXRoaW5nIHdlIHdhbnQgYWN0dWFsbHksIHNvIHdlIHdpbGwga2VlcCBpdCBzb21ldGhpbmcgaWRlbnRpZmlhYmxlLg0KDQpgYGB7cn0NCnNpbXBsZV9yZWMgJT4lDQogIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikNCmBgYA0KDQpXZSBtaWdodCBhbHNvIHdhbnQgdG8gcmVtb3ZlIHZhcmlhYmxlcyB0aGF0IGFwcGVhciB0byBiZSByZWR1bmRhbnQgYW5kIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIG90aGVycywgYXMgd2Uga25vdyBmcm9tIG91ciBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHRoYXQgbWFueSBvZiBvdXIgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkIHdpdGggb25lIGFub3RoZXIuIA0KV2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGBzdGVwX2NvcnIoKWAgZnVuY3Rpb24uDQoNCldlIGRvbid0IHdhbnQgdG8gcmVtb3ZlIHNvbWUgb2Ygb3VyIHZhcmlhYmxlcywgbGlrZSB0aGUgYENNQVFgIGFuZCBgYW9kYCB2YXJpYWJsZXMsIHdlIGNhbiBzcGVjaWZ5IHRoaXMgdXNpbmcgdGhlIGAtYCBzaWduIGJlZm9yZSB0aGUgbmFtZXMgb2YgdGhlc2UgdmFyaWFibGVzIGxpa2Ugc286DQoNCmBgYHtyfQ0Kc2ltcGxlX3JlYyAlPiUNCiAgc3RlcF9jb3JyKGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpDQpgYGANCg0KDQpJdCBpcyBhbHNvIGEgZ29vZCBpZGVhIHRvIHJlbW92ZSB2YXJpYWJsZXMgd2l0aCBuZWFyLXplcm8gdmFyaWFuY2UsIHdoaWNoIGNhbiBiZSBkb25lIHdpdGggdGhlIGBzdGVwX256digpYCBmdW5jdGlvbi4gDQoNClZhcmlhYmxlcyBoYXZlIGxvdyB2YXJpYW5jZSBpZiBhbGwgdGhlIHZhbHVlcyBhcmUgdmVyeSBzaW1pbGFyLCB0aGUgdmFsdWVzIGFyZSB2ZXJ5IHNwYXJzZSwgb3IgaWYgdGhleSBhcmUgaGlnaGx5IGltYmFsYW5jZWQuIEFnYWluIHdlIGRvbid0IHdhbnQgdG8gcmVtb3ZlIG91ciBgQ01BUWAgYW5kIGBhb2RgIHZhcmlhYmxlcy4NCg0KYGBge3J9DQpzaW1wbGVfcmVjICU+JQ0KICBzdGVwX256dihhbGxfcHJlZGljdG9ycygpLCAtIENNQVEsIC0gYW9kKQ0KYGBgDQoNCjxkZXRhaWxzPjxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIGxlYXJuIGFib3V0IGV4YW1wbGVzIHdoZXJlIHlvdSBtaWdodCBoYXZlIG5lYXItemVybyB2YXJpYW5jZSB2YXJpYWJsZXM8L3N1bW1hcnk+DQoNCjEpICoqU2ltaWxhciBWYWx1ZXMqKiAtIElmIHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgd2FzIG5lYXJseSB0aGUgc2FtZSBmb3IgZXZlcnkgemN0YSB0aGF0IGNvbnRhaW5lZCBhIG1vbml0b3IsIHRoZW4ga25vd2luZyB0aGUgcG9wdWxhdGlvbiBkZW5zaXR5IG5lYXIgb3VyIG1vbml0b3Igd291bGQgY29udHJpYnV0ZSBsaXR0bGUgdG8gb3VyIG1vZGVsIGluIGFzc2lzdGluZyB1cyB0byBwcmVkaWN0IG1vbml0b3IgYWlyIHBvbGx1dGlvbiB2YWx1ZXMuIA0KMikgKipTcGFyc2UgRGF0YSoqIC0gSWYgYWxsIG9mIHRoZSBtb25pdG9ycyB3ZXJlIGluIGxvY2F0aW9ucyB3aGVyZSB0aGUgcG9wdWxhdGlvbnMgZGlkIG5vdCBhdHRlbmQgZ3JhZHVhdGUgc2Nob29sLCB0aGVuIHRoZXNlIHZhbHVlcyB3b3VsZCBtb3N0bHkgYmUgemVybywgYWdhaW4gdGhpcyB3b3VsZCBkbyB2ZXJ5IGxpdHRsZSB0byBoZWxwIHVzIGRpc3Rpbmd1aXNoIG91ciBhaXIgcG9sbHV0aW9uIG1vbml0b3JzLldoZW4gbWFueSBvZiB0aGUgdmFsdWVzIGFyZSB6ZXJvIHRoaXMgaXMgYWxzbyBjYWxsZWQgc3BhcnNlIGRhdGEuICANCjMpICoqSW1iYWxhbmNlZCBEYXRhKiogSWYgbmVhcmx5IGFsbCBvZiB0aGUgbW9uaXRvcnMgd2VyZSBsb2NhdGVkIGluIG9uZSBwYXJ0aWN1bGFyIHN0YXRlLCBhbmQgYWxsIHRoZSBvdGhlcnMgb25seSBoYWQgb25lIG1vbml0b3IgZWFjaCwgdGhlbiB0aGUgcmVhbCBwcmVkaWN0aXZlIHZhbHVlIHdvdWxkIHNpbXBseSBiZSBpbiBrbm93aW5nIGlmIGEgbW9uaXRvciBpcyBsb2NhdGVkIGluIHRoYXQgcGFydGljdWxhciBzdGF0ZSBvciBub3QuIEluIHRoaXMgY2FzZSB3ZSBkb24ndCB3YW50IHRvIHJlbW92ZSBvdXIgdmFyaWFibGUsIHdlIGp1c3Qgd2FudCB0byBzaW1wbGlmeSBpdC4NCg0KU2VlIHRoaXMgW2Jsb2cgcG9zdF0oaHR0cHM6Ly93d3cuci1ibG9nZ2Vycy5jb20vbmVhci16ZXJvLXZhcmlhbmNlLXByZWRpY3RvcnMtc2hvdWxkLXdlLXJlbW92ZS10aGVtLyl7dGFyZ2V0PSJfYmxhbmsifSBhYm91dCB3aHkgcmVtb3ZpbmcgbmVhci16ZXJvIHZhcmlhbmNlIHZhcmlhYmxlcyBpc24ndCBhbHdheXMgYSBnb29kIGlkZWEgaWYgd2UgdGhpbmsgdGhhdCBhIHZhcmlhYmxlIG1pZ2h0IGJlIGVzcGVjaWFsbHkgaW5mb3JtYXRpdmUuDQoNCjwvZGV0YWlscz4NCg0KTGV0J3MgcHV0IGFsbCB0aGlzIHRvZ2V0aGVyIG5vdy4gDQoNCioqUmVtZW1iZXI6IGl0IGlzIGltcG9ydGFudCB0byBhZGQgdGhlIHN0ZXBzIHRvIHRoZSByZWNpcGUgaW4gYW4gb3JkZXIgdGhhdCBtYWtlcyBzZW5zZSBqdXN0IGxpa2Ugd2l0aCBhIGNvb2tpbmcgcmVjaXBlLioqDQoNCkZpcnN0LCB3ZSBhcmUgZ29pbmcgdG8gY3JlYXRlIG51bWVyaWMgdmFsdWVzIGZvciBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzLCB0aGVuIHdlIHdpbGwgbG9vayBhdCBjb3JyZWxhdGlvbiBhbmQgbmVhci16ZXJvIHZhcmlhbmNlLiANCkFnYWluLCB3ZSBkbyBub3Qgd2FudCB0byByZW1vdmUgdGhlIGBDTUFRYCBhbmQgYGFvZGAgdmFyaWFibGVzLCBzbyB3ZSBjYW4gbWFrZSBzdXJlIHRoZXkgYXJlIGtlcHQgaW4gdGhlIG1vZGVsIGJ5IGV4Y2x1ZGluZyB0aGVtIGZyb20gdGhvc2Ugc3RlcHMuIA0KSWYgd2Ugc3BlY2lmaWNhbGx5IHdhbnRlZCB0byByZW1vdmUgYSBwcmVkaWN0b3Igd2UgY291bGQgdXNlIGBzdGVwX3JtKClgLg0KDQpgYGB7cn0NCnNpbXBsZV9yZWMgJTw+JQ0KICB1cGRhdGVfcm9sZSgiZmlwcyIsIG5ld19yb2xlID0gImNvdW50eSBpZCIpICU+JQ0KICBzdGVwX2R1bW15KHN0YXRlLCBjb3VudHksIGNpdHksIHpjdGEsIG9uZV9ob3QgPSBUUlVFKSAlPiUNCiAgc3RlcF9jb3JyKGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpJT4lDQogIHN0ZXBfbnp2KGFsbF9wcmVkaWN0b3JzKCksIC0gQ01BUSwgLSBhb2QpDQogIA0Kc2ltcGxlX3JlYw0KYGBgDQoNCg0KDQojIyAqKlJ1bm5pbmcgdGhlIHByZS1wcm9jZXNzaW5nKioNCioqKg0KDQojIyMgKipTdGVwIDE6IFVwZGF0ZSB0aGUgcmVjaXBlIHdpdGggdHJhaW5pbmcgZGF0YSB1c2luZyBgcHJlcCgpYCoqDQoqKioNCg0KVGhlIG5leHQgbWFqb3IgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlIGlzIGBwcmVwKClgLg0KVGhpcyBmdW5jdGlvbiB1cGRhdGVzIHRoZSByZWNpcGUgb2JqZWN0IGJhc2VkIG9uIHRoZSB0cmFpbmluZyBkYXRhLiANCkl0IGVzdGltYXRlcyBwYXJhbWV0ZXJzIChlc3RpbWF0aW5nIHRoZSByZXF1aXJlZCBxdWFudGl0aWVzIGFuZCBzdGF0aXN0aWNzIHJlcXVpcmVkIGJ5IHRoZSBzdGVwcyBmb3IgdGhlIHZhcmlhYmxlcykgZm9yIHByZS1wcm9jZXNzaW5nIGFuZCB1cGRhdGVzIHRoZSB2YXJpYWJsZXMgcm9sZXMsIGFzIHNvbWUgb2YgdGhlIHByZWRpY3RvcnMgbWF5IGJlIHJlbW92ZWQsIHRoaXMgYWxsb3dzIHRoZSByZWNpcGUgdG8gYmUgcmVhZHkgdG8gdXNlIG9uIG90aGVyIGRhdGEgc2V0cy4gDQpJdCAqKmRvZXMgbm90IG5lY2Vzc2FyaWx5IGFjdHVhbGx5IGV4ZWN1dGUgdGhlIHByZS1wcm9jZXNzaW5nIGl0c2VsZioqLCBob3dldmVyIHdlIHdpbGwgc3BlY2lmeSBpbiBhcmd1bWVudCBmb3IgaXQgdG8gZG8gdGhpcyBzbyB0aGF0IHdlIGNhbiB0YWtlIGEgbG9vayBhdCB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhLg0KDQoNClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBhcmd1bWVudHMgdG8ga25vdyBhYm91dDoNCg0KMS4gYHRyYWluaW5nYCAtIHlvdSBtdXN0IHN1cHBseSBhIHRyYWluaW5nIGRhdGEgc2V0IHRvIGVzdGltYXRlIHBhcmFtZXRlcnMgZm9yIHByZS1wcm9jZXNzaW5nIG9wZXJhdGlvbnMgKHJlY2lwZSBzdGVwcykgLSB0aGlzIG1heSBhbHJlYWR5IGJlIGluY2x1ZGVkIGluIHlvdXIgcmVjaXBlIC0gYXMgaXMgdGhlIGNhc2UgZm9yIHVzDQoyLiBgZnJlc2hgIC0gaWYgYGZyZXNoPVRSVUVgLCAtIHdpbGwgcmV0cmFpbiBhbmQgZXN0aW1hdGUgcGFyYW1ldGVycyBmb3IgYW55IHByZXZpb3VzIHN0ZXBzIHRoYXQgd2VyZSBhbHJlYWR5IHByZXBwZWQgaWYgeW91IGFkZCBtb3JlIHN0ZXBzIHRvIHRoZSByZWNpcGUNCjMuIGB2ZXJib3NlYCAtIGlmIGB2ZXJib3NlPVRSVUVgLCBzaG93cyB0aGUgcHJvZ3Jlc3MgYXMgdGhlIHN0ZXBzIGFyZSBldmFsdWF0ZWQgYW5kIHRoZSBzaXplIG9mIHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIHNldA0KNC4gYHJldGFpbmAgLSBpZiBgcmV0YWluPVRSVUVgLCB0aGVuIHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIHNldCB3aWxsIGJlIHNhdmVkIHdpdGhpbiB0aGUgcmVjaXBlIChhcyB0ZW1wbGF0ZSkuIFRoaXMgaXMgZ29vZCBpZiB5b3UgYXJlIGxpa2VseSB0byBhZGQgbW9yZSBzdGVwcyBhbmQgZG8gbm90IHdhbnQgdG8gcmVydW4gdGhlIGBwcmVwKClgIG9uIHRoZSBwcmV2aW91cyBzdGVwcy4gSG93ZXZlciB0aGlzIGNhbiBtYWtlIHRoZSByZWNpcGUgc2l6ZSBsYXJnZS4gVGhpcyBpcyBuZWNlc3NhcnkgaWYgeW91IHdhbnQgdG8gYWN0dWFsbHkgbG9vayBhdCB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhLg0KDQpMZXQncyB0cnkgb3V0IHRoZSBgcHJlcCgpYCBmdW5jdGlvbjogDQoNCmBgYHtyfQ0KcHJlcHBlZF9yZWMgPC0gcHJlcChzaW1wbGVfcmVjLCB2ZXJib3NlID0gVFJVRSwgcmV0YWluID0gVFJVRSApDQpuYW1lcyhwcmVwcGVkX3JlYykNCmBgYA0KDQpUaGVyZSBhcmUgYWxzbyBsb3RzIG9mIHVzZWZ1bCB0aGluZ3MgdG8gY2hlY2tvdXQgaW4gdGhlIG91dHB1dCBvZiBgcHJlcCgpYC4NCllvdSBjYW4gc2VlOg0KDQoxLiB0aGUgYHN0ZXBzYCB0aGF0IHdlcmUgcnVuICANCjIuIHRoZSBvcmlnaW5hbCB2YXJpYWJsZSBpbmZvIChgdmFyX2luZm9gKSAgDQozLiB0aGUgdXBkYXRlZCB2YXJpYWJsZSBpbmZvIGFmdGVyIHByZS1wcm9jZXNzaW5nIChgdGVybV9pbmZvYCkNCjQuIHRoZSBuZXcgYGxldmVsc2Agb2YgdGhlIHZhcmlhYmxlcyANCjUuIHRoZSBvcmlnaW5hbCBsZXZlbHMgb2YgdGhlIHZhcmlhYmxlcyAoYG9yaWdfbHZsc2ApDQo2LiBpbmZvIGFib3V0IHRoZSB0cmFpbmluZyBkYXRhIHNldCBzaXplIGFuZCBjb21wbGV0ZW5lc3MgKGB0cl9pbmZvYCkNCg0KKipOb3RlKio6IFlvdSBtYXkgc2VlIHRoZSBgcHJlcC5yZWNpcGUoKWAgZnVuY3Rpb24gaW4gbWF0ZXJpYWwgdGhhdCB5b3UgcmVhZCBhYm91dCB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuIFRoaXMgaXMgcmVmZXJyaW5nIHRvIHRoZSBgcHJlcCgpYCBmdW5jdGlvbiBvZiB0aGUgYHJlY2lwZXNgIHBhY2thZ2UuDQoNCg0KIyMjICoqU3RlcCAyOiBFeHRyYWN0IHByZS1wcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSB1c2luZyBgYmFrZSgpYCoqDQoqKioNCg0KDQpTaW5jZSB3ZSByZXRhaW5lZCBvdXIgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIChpLmUuIGBwcmVwKHJldGFpbj1UUlVFKWApLCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgaXQgbGlrZSBieSB1c2luZyB0aGUgYGJha2UoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlIGxpa2UgdGhpczoNCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNDAwcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidHJhaW5pbmdfcHJlcHJvY2Vzc2luZ19yZWNpcGVzMy5wbmciKSkNCmBgYA0KDQpMZXQncyBiYWtlISANCg0KU2luY2Ugd2UgZG9uJ3QgaGF2ZSBuZXcgZGF0YSAod2UgYXJlbid0IGxvb2tpbmcgYXQgdGhlIHRlc3RpbmcgZGF0YSksIHdlIG5lZWQgdG8gc3BlY2lmeSB0aGlzIHdpdGggYG5ld19kYXRhID0gTlVMTGAuDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KYmFrZWRfdHJhaW4gPC0gYmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSBOVUxMKQ0KZ2xpbXBzZShiYWtlZF90cmFpbikNCmBgYA0KIyMjIw0KDQoqKk5vdGUqKi0gdGhpcyBwcm9jZXNzIHVzZWQgdG8gcmVxdWlyZSB0aGUgYGp1aWNlKClgIGZ1bmN0aW9uLg0KDQpGb3IgZWFzeSBjb21wYXJpc29uIHNha2UgLSBoZXJlIGlzIG91ciBvcmlnaW5hbCBkYXRhOg0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQoNCmBgYHtyfQ0KIyBTY3JvbGwgdGhyb3VnaCB0aGUgb3V0cHV0IQ0KZ2xpbXBzZShwbSkNCmBgYA0KIyMjIw0KDQpOb3RpY2UgaG93IHdlIG9ubHkgaGF2ZSAzNiB2YXJpYWJsZXMgbm93IGluc3RlYWQgb2YgNTAhIA0KVHdvIG9mIHRoZXNlIGFyZSBvdXIgSUQgdmFyaWFibGVzIChgZmlwc2AgYW5kIHRoZSBhY3R1YWwgbW9uaXRvciBJRCAoYGlkYCkpIGFuZCBvbmUgaXMgb3VyIG91dGNvbWUgKGB2YWx1ZWApLiANClRodXMgd2Ugb25seSBoYXZlIDMzIHByZWRpY3RvcnMgbm93LiANCldlIGNhbiBhbHNvIHNlZSB0aGF0IHdlIG5vIGxvbmdlciBoYXZlIGFueSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuIA0KVmFyaWFibGVzIGxpa2UgYHN0YXRlYCBhcmUgZ29uZSBhbmQgb25seSBgc3RhdGVfQ2FsaWZvcm5pYWAgcmVtYWlucyBhcyBpdCB3YXMgdGhlIG9ubHkgc3RhdGUgaWRlbnRpdHkgdG8gaGF2ZSBub256ZXJvIHZhcmlhbmNlLg0KV2UgY2FuIGFsc28gc2VlIHRoYXQgdGhlcmUgd2VyZSBtb3JlIG1vbml0b3JzIGxpc3RlZCBhcyBgIk5vdCBpbiBhIGNpdHkiYCB0aGFuIGFueSBjaXR5LiANCg0KV2UgY2FuIHNlZSB0aGF0IENhbGlmb3JuaWEgaGFkIHRoZSBsYXJnZXN0IG51bWJlciBvZiBtb25pdG9ycyBjb21wYXJlZCB0byB0aGUgb3RoZXIgc3RhdGVzLg0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFfQ0KcG0gJT4lIGNvdW50KHN0YXRlKSANCmBgYA0KDQoNClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6DQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCnBtICU+JSBjb3VudChzdGF0ZSkgICU+JQ0KICBwcmludChuID0gMWUzKQ0KYGBgDQoNCiMjIyMNCg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCnBtICU+JSBjb3VudChjaXR5KQ0KYGBgDQoNClNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQ6DQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCg0KYGBge3IsIGVjaG89RkFMU0V9DQpwbSAlPiUgY291bnQoY2l0eSkgJT4lDQogIHByaW50KG4gPSAxZTMpDQpgYGANCg0KIyMjIw0KDQoqKk5vdGUqKjogUmVjYWxsIHRoYXQgeW91IG11c3Qgc3BlY2lmeSBgcmV0YWluID0gVFJVRWAgYXJndW1lbnQgb2YgdGhlIGBwcmVwKClgIGZ1bmN0aW9uIHRvIHVzZSBgYmFrZSgpYC4NCg0KIyMjICoqU3RlcCAzOiBFeHRyYWN0IHByZS1wcm9jZXNzZWQgdGVzdGluZyBkYXRhIHVzaW5nIGBiYWtlKClgKioNCioqKg0KDQpBY2NvcmRpbmcgdG8gdGhlIGB0aWR5bW9kZWxzYCBkb2N1bWVudGF0aW9uOg0KDQo+IGBiYWtlKClgIHRha2VzIGEgdHJhaW5lZCByZWNpcGUgYW5kIGFwcGxpZXMgdGhlIG9wZXJhdGlvbnMgdG8gYSBkYXRhIHNldCB0byBjcmVhdGUgYSBkZXNpZ24gbWF0cml4Lg0KIEZvciBleGFtcGxlOiBpdCBhcHBsaWVzIHRoZSBjZW50ZXJpbmcgdG8gbmV3IGRhdGEgc2V0cyB1c2luZyB0aGVzZSBtZWFucyB1c2VkIHRvIGNyZWF0ZSB0aGUgcmVjaXBlLg0KDQpUaGVyZWZvcmUsIGlmIHlvdSB3YW50ZWQgdG8gbG9vayBhdCB0aGUgcHJlLXByb2Nlc3NlZCB0ZXN0aW5nIGRhdGEgeW91IHdvdWxkIHVzZSB0aGUgYGJha2UoKWAgZnVuY3Rpb24gb2YgdGhlIGByZWNpcGVzYCBwYWNrYWdlLg0KKFlvdSBnZW5lcmFsbHkgd2FudCB0byBsZWF2ZSB5b3VyIHRlc3RpbmcgZGF0YSBhbG9uZSwgYnV0IGl0IGlzIGdvb2QgdG8gbG9vayBmb3IgaXNzdWVzIGxpa2UgdGhlIGludHJvZHVjdGlvbiBvZiBOQSB2YWx1ZXMpLg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI0MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJ0ZXN0aW5nX3ByZXByb2Nlc3NpbmdfcmVjaXBlczQucG5nIikpDQpgYGANCg0KTGV0J3MgYmFrZSEgDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCmBgYHtyLH0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCmJha2VkX3Rlc3RfcG0gPC0gcmVjaXBlczo6YmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSB0ZXN0X3BtKQ0KZ2xpbXBzZShiYWtlZF90ZXN0X3BtKQ0KYGBgDQojIyMjDQoNCg0KTm90aWNlIHRoYXQgb3VyIGBjaXR5X05vdC5pbi5hLmNpdHlgIHZhcmlhYmxlIHNlZW1zIHRvIGJlIE5BIHZhbHVlcy4gDQpXaHkgbWlnaHQgdGhhdCBiZT8NCg0KQWghIFBlcmhhcHMgaXQgaXMgYmVjYXVzZSBzb21lIG9mIG91ciBsZXZlbHMgd2VyZSBub3QgcHJldmlvdXNseSBzZWVuIGluIHRoZSB0cmFpbmluZyBzZXQhDQoNCkxldCdzIHRha2UgYSBsb29rIHVzaW5nIHRoZSBbc2V0IG9wZXJhdGlvbnNdKGh0dHBzOi8vd3d3LnByb2JhYmlsaXR5Y291cnNlLmNvbS9jaGFwdGVyMS8xXzJfMl9zZXRfb3BlcmF0aW9ucy5waHApe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gDQpXZSBjYW4gdGFrZSBhIGxvb2sgYXQgY2l0aWVzIHRoYXQgd2VyZSBkaWZmZXJlbnQgYmV0d2VlbiB0aGUgdGVzdCBhbmQgdHJhaW5pbmcgc2V0Lg0KDQpgYGB7cn0NCnRyYWluY2l0aWVzIDwtIHRyYWluX3BtICU+JSBkaXN0aW5jdChjaXR5KQ0KdGVzdGNpdGllcyA8LSB0ZXN0X3BtICU+JSBkaXN0aW5jdChjaXR5KQ0KDQojZ2V0IHRoZSBudW1iZXIgb2YgY2l0aWVzIHRoYXQgd2VyZSBkaWZmZXJlbnQNCmRpbShkcGx5cjo6c2V0ZGlmZih0cmFpbmNpdGllcywgdGVzdGNpdGllcykpDQoNCiNnZXQgdGhlIG51bWJlciBvZiBjaXRpZXMgdGhhdCBvdmVybGFwcGVkDQpkaW0oZHBseXI6OmludGVyc2VjdCh0cmFpbmNpdGllcywgdGVzdGNpdGllcykpDQpgYGANCg0KSW5kZWVkLCB0aGVyZSBhcmUgbG90cyBvZiBkaWZmZXJlbnQgY2l0aWVzIGluIG91ciB0ZXN0IGRhdGEgdGhhdCBhcmUgbm90IGluIG91ciB0cmFpbmluZyBkYXRhIQ0KDQoNClNvLCBsZXQgZ28gYmFjayB0byBvdXIgYHBtYCBkYXRhIHNldCBhbmQgbW9kaWZ5IHRoZSBgY2l0eWAgdmFyaWFibGUgdG8ganVzdCBiZSB2YWx1ZXMgb2YgYGluIGEgY2l0eWAgb3IgYG5vdCBpbiBhIGNpdHlgIHVzaW5nIHRoZSBgY2FzZV93aGVuKClgIGZ1bmN0aW9uIG9mIGBkcGx5cmAuDQpUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gdmVjdG9yaXplIG11bHRpcGxlIGBpZl9lbHNlKClgIHN0YXRlbWVudHMuDQoNCmBgYHtyfQ0KcG0gJT4lDQogIG11dGF0ZShjaXR5ID0gY2FzZV93aGVuKGNpdHkgPT0gIk5vdCBpbiBhIGNpdHkiIH4gIk5vdCBpbiBhIGNpdHkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjaXR5ICE9ICJOb3QgaW4gYSBjaXR5IiB+ICJJbiBhIGNpdHkiKSkNCmBgYA0KDQpBbHRlcm5hdGl2ZWx5IHlvdSBjb3VsZCBjcmVhdGUgYSBbY3VzdG9tIHN0ZXAgZnVuY3Rpb25dKGh0dHBzOi8vcmVjaXBlcy50aWR5bW9kZWxzLm9yZy9hcnRpY2xlcy9DdXN0b21fU3RlcHMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB0byBkbyB0aGlzIGFuZCBhZGQgdGhpcyB0byB5b3VyIHJlY2lwZSwgYnV0IHRoYXQgaXMgYmV5b25kIHRoZSBzY29wZSBvZiB0aGlzIGNhc2Ugc3R1ZHkuIA0KDQpXZSB3aWxsIG5lZWQgdG8gcmVwZWF0IGFsbCB0aGUgc3RlcHMgKHNwbGl0dGluZyB0aGUgZGF0YSwgcHJlLXByb2Nlc3NpbmcsIGV0YykgYXMgdGhlIGxldmVscyBvZiBvdXIgdmFyaWFibGVzIGhhdmUgbm93IGNoYW5nZWQuIA0KDQpXaGlsZSB3ZSBhcmUgZG9pbmcgdGhpcywgd2UgbWlnaHQgYWxzbyBoYXZlIHRoaXMgaXNzdWUgZm9yIGBjb3VudHlgLiANCg0KVGhlIGBjb3VudHlgIHZhcmlhYmxlcyBhcHBlYXJzIHRvIGdldCBkcm9wcGVkIGR1ZSB0byBlaXRoZXIgY29ycmVsYXRpb24gb3IgbmVhciB6ZXJvIHZhcmlhbmNlLiANCg0KSXQgaXMgbGlrZWx5IGR1ZSB0byBuZWFyIHplcm8gdmFyaWFuY2UgYmVjYXVzZSB0aGlzIGlzIHRoZSBtb3JlIGdyYW51bGFyIG9mIHRoZXNlIGdlb2dyYXBoaWMgY2F0ZWdvcmljYWwgdmFyaWFibGVzIGFuZCBsaWtlbHkgc3BhcnNlLg0KDQpgYGB7cn0NCnBtICU8PiUNCiAgbXV0YXRlKGNpdHkgPSBjYXNlX3doZW4oY2l0eSA9PSAiTm90IGluIGEgY2l0eSIgfiAiTm90IGluIGEgY2l0eSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGNpdHkgIT0gIk5vdCBpbiBhIGNpdHkiIH4gIkluIGEgY2l0eSIpKQ0KDQpzZXQuc2VlZCgxMjM0KSAjIHNhbWUgc2VlZCBhcyBiZWZvcmUNCnBtX3NwbGl0IDwtcnNhbXBsZTo6aW5pdGlhbF9zcGxpdChkYXRhID0gcG0sIHByb3AgPSAyLzMpDQpwbV9zcGxpdA0KIHRyYWluX3BtIDwtcnNhbXBsZTo6dHJhaW5pbmcocG1fc3BsaXQpDQogdGVzdF9wbSA8LXJzYW1wbGU6OnRlc3RpbmcocG1fc3BsaXQpDQpgYGANCg0KDQojIyMjIHsucmVjYWxsX2NvZGVfcXVlc3Rpb25fYmxvY2t9DQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4NCg0KU2VlIGlmIHlvdSBjYW4gY29tZSB1cCB3aXRoIHRoZSBjb2RlIGZvciB0aGUgbmV3IHJlY2lwZS4NCg0KIyMjIw0KDQoqKioNCg0KPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgY29kZSBmb3IgdGhlIG5ldyByZWNpcGUuIDwvc3VtbWFyeT4NCg0KDQpgYGB7cn0NCm5vdmVsX3JlYyA8LXJlY2lwZSh0cmFpbl9wbSkgJT4lDQogICAgdXBkYXRlX3JvbGUoZXZlcnl0aGluZygpLCBuZXdfcm9sZSA9ICJwcmVkaWN0b3IiKSAlPiUNCiAgICB1cGRhdGVfcm9sZSh2YWx1ZSwgbmV3X3JvbGUgPSAib3V0Y29tZSIpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lDQogICAgc3RlcF9kdW1teShzdGF0ZSwgY291bnR5LCBjaXR5LCB6Y3RhLCBvbmVfaG90ID0gVFJVRSkgJT4lDQogICAgc3RlcF9jb3JyKGFsbF9udW1lcmljKCkpICU+JQ0KICAgIHN0ZXBfbnp2KGFsbF9udW1lcmljKCkpIA0KYGBgDQo8L2RldGFpbHM+DQoqKioNCg0KYGBge3J9DQpub3ZlbF9yZWMNCmBgYA0KDQoNCg0KTm93IGxldCdzIHJldHJhaW4gb3VyIHRyYWluaW5nIGRhdGEgYW5kIHRyeSBiYWtpbmcgb3VyIHRlc3QgZGF0YS4NCg0KDQoNCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30NCjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPg0KDQpEbyB5b3UgcmVjYWxsIGhvdyB0byBwcmUtcHJvY2VzcyBhbmQgZXh0cmFjdCB0aGUgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhPw0KDQojIyMjDQoNCioqKg0KDQo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4NCg0KYGBge3J9DQpwcmVwcGVkX3JlYyA8LSBwcmVwKG5vdmVsX3JlYywgdmVyYm9zZSA9IFRSVUUsIHJldGFpbiA9IFRSVUUpDQpiYWtlZF90cmFpbiA8LSBiYWtlKHByZXBwZWRfcmVjLCBuZXdfZGF0YSA9IE5VTEwpDQpgYGANCjwvZGV0YWlscz4gDQoqKioNCg0KDQojIyMjIHsuc2Nyb2xsYWJsZSB9DQpgYGB7cn0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCmdsaW1wc2UoYmFrZWRfdHJhaW4pDQpgYGANCg0KIyMjIw0KDQpBbmQgbm93LCBsZXQncyB0cnkgYmFraW5nIG91ciB0ZXN0IHNldCB0byBzZWUgaWYgd2Ugc3RpbGwgaGF2ZSBgTkFgIHZhbHVlcy4NCg0KIyMjIyB7LnNjcm9sbGFibGUgfQ0KDQpgYGB7cn0NCiMgU2Nyb2xsIHRocm91Z2ggdGhlIG91dHB1dCENCmJha2VkX3Rlc3RfcG0gPC0gcmVjaXBlczo6YmFrZShwcmVwcGVkX3JlYywgbmV3X2RhdGEgPSB0ZXN0X3BtKQ0KDQpnbGltcHNlKGJha2VkX3Rlc3RfcG0pDQpgYGANCg0KIyMjIw0KDQpHcmVhdCwgbm93IHdlIG5vIGxvbmdlciBoYXZlIGBOQWAgdmFsdWVzISA6KQ0KDQoqKk5vdGUqKjogaWYgeW91IHVzZSB0aGUgc2tpcCBvcHRpb24gZm9yIHNvbWUgb2YgdGhlIHByZS1wcm9jZXNzaW5nIHN0ZXBzLCBiZSBjYXJlZnVsLiANCmBqdWljZSgpYCB3aWxsIHNob3cgYWxsIG9mIHRoZSByZXN1bHRzIGlnbm9yaW5nIGBza2lwID0gVFJVRWAgKGFzIHlvdSBjYW4gc3RpbGwgdXNlIHRoaXMgZnVuY3Rpb24gaWYgeW91IHBlcmZlciBpdCB0byBgYmFrZSgpYCkuDQpgYmFrZSgpYCB3aWxsIG5vdCBuZWNlc3NhcmlseSBjb25kdWN0IHRoZXNlIHN0ZXBzIG9uIHRoZSBuZXcgZGF0YS4NCg0KDQojIyAqKlNwZWNpZnlpbmcgdGhlIG1vZGVsKioNCioqKg0KDQpTbyBmYXIgd2UgaGF2ZSB1c2VkIHRoZSBwYWNrYWdlcyBgcnNhbXBsZWAgdG8gc3BsaXQgdGhlIGRhdGEgYW5kIGByZWNpcGVzYCB0byBhc3NpZ24gdmFyaWFibGUgdHlwZXMsIGFuZCB0byBzcGVjaWZ5IGFuZCBwcmVwIG91ciBwcmUtcHJvY2Vzc2luZyAoYXMgd2VsbCBhcyB0byBvcHRpb25hbGx5IGV4dHJhY3QgdGhlIHByZS1wcm9jZXNzZWQgZGF0YSkuDQoNCldlIHdpbGwgbm93IHVzZSB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgKHdoaWNoIGlzIHNpbWlsYXIgdG8gdGhlIHByZXZpb3VzIGBjYXJldGAgcGFja2FnZSAtIGFuZCBoZW5jZSB3aHkgaXQgaXMgbmFtZWQgYWZ0ZXIgdGhlIHZlZ2V0YWJsZSkgdG8gc3BlY2lmeSBvdXIgbW9kZWwuDQoNClRoZXJlIGFyZSBmb3VyIHRoaW5ncyB3ZSBuZWVkIHRvIGRlZmluZSBhYm91dCBvdXIgbW9kZWw6ICANCg0KMS4gVGhlICoqdHlwZSoqIG9mIG1vZGVsICh1c2luZyBzcGVjaWZpYyBmdW5jdGlvbnMgaW4gcGFyc25pcCBsaWtlIGByYW5kX2ZvcmVzdCgpYCwgYGxvZ2lzdGljX3JlZygpYCBldGMuKSAgDQoyLiBUaGUgcGFja2FnZSBvciAqKmVuZ2luZSoqIHRoYXQgd2Ugd2lsbCB1c2UgdG8gaW1wbGVtZW50IHRoZSB0eXBlIG9mIG1vZGVsIHNlbGVjdGVkICh1c2luZyB0aGUgYHNldF9lbmdpbmUoKWAgZnVuY3Rpb24pIA0KMy4gVGhlICoqbW9kZSoqIG9mIGxlYXJuaW5nIC0gY2xhc3NpZmljYXRpb24gb3IgcmVncmVzc2lvbiAodXNpbmcgdGhlIGBzZXRfbW9kZSgpYCBmdW5jdGlvbikgDQo0LiBBbnkgKiphcmd1bWVudHMqKiBuZWNlc3NhcnkgZm9yIHRoZSBtb2RlbC9wYWNrYWdlIHNlbGVjdGVkICh1c2luZyB0aGUgYHNldF9hcmdzKClgZnVuY3Rpb24gLSAgZm9yIGV4YW1wbGUgdGhlIGBtdHJ5ID1gIGFyZ3VtZW50IGZvciByYW5kb20gZm9yZXN0IHdoaWNoIGlzIHRoZSBudW1iZXIgb2YgdmFyaWFibGVzIHRvIGJlIHVzZWQgYXMgb3B0aW9ucyBmb3Igc3BsaXR0aW5nIGF0IGVhY2ggdHJlZSBub2RlKQ0KDQpMZXQncyB3YWxrIHRocm91Z2ggdGhlc2Ugc3RlcHMgb25lIGJ5IG9uZS4gDQpGb3Igb3VyIGNhc2UsIHdlIGFyZSBnb2luZyB0byBzdGFydCBvdXIgYW5hbHlzaXMgd2l0aCBhIGxpbmVhciByZWdyZXNzaW9uIGJ1dCB3ZSB3aWxsIGRlbW9uc3RyYXRlIGhvdyB3ZSBjYW4gdHJ5IGRpZmZlcmVudCBtb2RlbHMuDQoNClRoZSBmaXJzdCBzdGVwIGlzIHRvIGRlZmluZSB3aGF0IHR5cGUgb2YgbW9kZWwgd2Ugd291bGQgbGlrZSB0byB1c2UuIA0KU2VlIFtoZXJlXShodHRwczovL3d3dy50aWR5bW9kZWxzLm9yZy9maW5kL3BhcnNuaXAvKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb2RlbGluZyBvcHRpb25zIGluIGBwYXJzbmlwYC4NCg0KDQpgYGB7cn0NClBNX21vZGVsIDwtIHBhcnNuaXA6OmxpbmVhcl9yZWcoKSAjIFBNIHdhcyB1c2VkIGluIHRoZSBuYW1lIGZvciBwYXJ0aWN1bGF0ZSBtYXR0ZXINClBNX21vZGVsDQpgYGANCg0KT0suIFNvIGZhciwgYWxsIHdlIGhhdmUgZGVmaW5lZCBpcyB0aGF0IHdlIHdhbnQgdG8gdXNlIGEgbGluZWFyIHJlZ3Jlc3Npb24uLi4gIA0KTGV0J3MgdGVsbCBgcGFyc25pcGAgbW9yZSBhYm91dCB3aGF0IHdlIHdhbnQuDQoNCldlIHdvdWxkIGxpa2UgdG8gdXNlIHRoZSBbb3JkaW5hcnkgbGVhc3Qgc3F1YXJlc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvT3JkaW5hcnlfbGVhc3Rfc3F1YXJlcykgbWV0aG9kIHRvIGZpdCBvdXIgbGluZWFyIHJlZ3Jlc3Npb24uIA0KU28gd2Ugd2lsbCB0ZWxsIGBwYXJzbmlwYCB0aGF0IHdlIHdhbnQgdG8gdXNlIHRoZSBgbG1gIHBhY2thZ2UgdG8gaW1wbGVtZW50IG91ciBsaW5lYXIgcmVncmVzc2lvbiAodGhlcmUgYXJlIG1hbnkgb3B0aW9ucyBhY3R1YWxseSBzdWNoIGFzIFtgcnN0YW5gXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnN0YW4vdmlnbmV0dGVzL3JzdGFuLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIFtgZ2xtbmV0YF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dsbW5ldC9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9LCBbYGtlcmFzYF0oaHR0cHM6Ly9rZXJhcy5yc3R1ZGlvLmNvbS8pe3RhcmdldD0iX2JsYW5rIn0sIGFuZCBbYHNwYXJrbHlyYF0oaHR0cHM6Ly90aGVyaW5zcGFyay5jb20vc3RhcnRpbmcuaHRtbCNzdGFydGluZy1zcGFya2x5ci1oZWxsby13b3JsZCl7dGFyZ2V0PSJfYmxhbmsifSkuIFNlZSBbaGVyZV0oaHR0cHM6Ly9wYXJzbmlwLnRpZHltb2RlbHMub3JnL3JlZmVyZW5jZS9saW5lYXJfcmVnLmh0bWwpIGZvciBhIGRlc2NyaXB0aW9uIG9mIHRoZSBkaWZmZXJlbmNlcyBhbmQgdXNpbmcgdGhlc2UgZGlmZmVyZW50IGVuZ2luZXMgd2l0aCBgcGFyc25pcGAuDQoNCldlIHdpbGwgZG8gc28gYnkgdXNpbmcgdGhlIGBzZXRfZW5naW5lKClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZS4NCg0KYGBge3J9DQpsbV9QTV9tb2RlbCA8LSANCiAgUE1fbW9kZWwgICU+JQ0KICBwYXJzbmlwOjpzZXRfZW5naW5lKCJsbSIpDQoNCmxtX1BNX21vZGVsDQpgYGANCg0KSW4gc29tZSBjYXNlcyBzb21lIHBhY2thZ2VzIGNhbiBkbyBlaXRoZXIgY2xhc3NpZmljYXRpb24gb3IgcHJlZGljdGlvbiwgc28gaXQgaXMgYSBnb29kIGlkZWEgdG8gc3BlY2lmeSB3aGljaCBtb2RlIHlvdSBpbnRlbmQgdG8gcGVyZm9ybS4gDQpIZXJlLCB3ZSBhaW0gdG8gcHJlZGljdCB0aGUgYWlyIHBvbGx1dGlvbi4gDQpZb3UgY2FuIGRvIHRoaXMgd2l0aCB0aGUgYHNldF9tb2RlKClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZSwgYnkgdXNpbmcgZWl0aGVyIGBzZXRfbW9kZSgiY2xhc3NpZmljYXRpb24iKWAgb3IgYHNldF9tb2RlKCJyZWdyZXNzaW9uIilgLg0KDQpgYGB7cn0NCmxtX1BNX21vZGVsIDwtIA0KICBQTV9tb2RlbCAgJT4lDQogIHBhcnNuaXA6OnNldF9lbmdpbmUoImxtIikgJT4lDQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikNCg0KbG1fUE1fbW9kZWwNCmBgYA0KDQojIyAqKkZpdHRpbmcgdGhlIG1vZGVsKioNCioqKg0KDQpXZSBjYW4gIHVzZSB0aGUgYHBhcnNuaXBgIHBhY2thZ2Ugd2l0aCBhIG5ld2VyIHBhY2thZ2UgY2FsbGVkIGB3b3JrZmxvd3NgIHRvIGZpdCBvdXIgbW9kZWwuIA0KDQpUaGUgYHdvcmtmbG93c2AgcGFja2FnZSBhbGxvd3MgdXMgdG8ga2VlcCB0cmFjayBvZiBib3RoIG91ciBwcmUtcHJvY2Vzc2luZyBzdGVwcyBhbmQgb3VyIG1vZGVsIHNwZWNpZmljYXRpb24uIEl0IGFsc28gYWxsb3dzIHVzIHRvIGltcGxlbWVudCBmYW5jaWVyIG9wdGltaXphdGlvbnMgaW4gYW4gYXV0b21hdGVkIHdheSBhbmQgaXQgY2FuIGFsc28gaGFuZGxlIHBvc3QtcHJvY2Vzc2luZyBvcGVyYXRpb25zLiANCg0KDQpXZSBiZWdpbiBieSBjcmVhdGluZyBhIHdvcmtmbG93IHVzaW5nIHRoZSBgd29ya2Zsb3coKWAgZnVuY3Rpb24gaW4gdGhlIGB3b3JrZmxvd3NgIHBhY2thZ2UuIA0KDQpOZXh0LCB3ZSB1c2UgYGFkZF9yZWNpcGUoKWAgKG91ciBwcmUtcHJvY2Vzc2luZyBzcGVjaWZpY2F0aW9ucykgYW5kIHdlIGFkZCBvdXIgbW9kZWwgd2l0aCB0aGUgYGFkZF9tb2RlbCgpYCBmdW5jdGlvbiAtLSBib3RoIGZ1bmN0aW9ucyBmcm9tIHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlLg0KDQoqKk5vdGUqKjogV2UgZG8gbm90IG5lZWQgdG8gYWN0dWFsbHkgYHByZXAoKWAgb3VyIHJlY2lwZSBiZWZvcmUgdXNpbmcgd29ya2Zsb3dzIQ0KDQpJZiB5b3UgcmVjYWxsIGBub3ZlbF9yZWNgIGlzIHRoZSByZWNpcGUgd2UgcHJldmlvdXNseSBjcmVhdGVkIHdpdGggdGhlIGByZWNpcGVzYCBwYWNrYWdlIGFuZCBgbG1fUE1fbW9kZWxgIHdhcyBjcmVhdGVkIHdoZW4gd2Ugc3BlY2lmaWVkIG91ciBtb2RlbCB3aXRoIHRoZSBgcGFyc25pcGAgcGFja2FnZS4NCkhlcmUsIHdlIGNvbWJpbmUgZXZlcnl0aGluZyB0b2dldGhlciBpbnRvIGEgd29ya2Zsb3cuIA0KDQpgYGB7cn0NClBNX3dmbG93IDwtd29ya2Zsb3dzOjp3b3JrZmxvdygpICU+JQ0KICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUobm92ZWxfcmVjKSAlPiUNCiAgICAgICAgICAgd29ya2Zsb3dzOjphZGRfbW9kZWwobG1fUE1fbW9kZWwpDQpQTV93Zmxvdw0KYGBgDQoNCkFoLCBuaWNlLiANCk5vdGljZSBob3cgaXQgdGVsbHMgdXMgYWJvdXQgYm90aCBvdXIgcHJlLXByb2Nlc3Npbmcgc3RlcHMgYW5kIG91ciBtb2RlbCBzcGVjaWZpY2F0aW9ucy4NCg0KTmV4dCwgd2UgInByZXBhcmUgdGhlIHJlY2lwZSIgKG9yIGVzdGltYXRlIHRoZSBwYXJhbWV0ZXJzKSBhbmQgZml0IHRoZSBtb2RlbCB0byBvdXIgdHJhaW5pbmcgZGF0YSBhbGwgYXQgb25jZS4gDQpQcmludGluZyB0aGUgb3V0cHV0LCB3ZSBjYW4gc2VlIHRoZSBjb2VmZmljaWVudHMgb2YgdGhlIG1vZGVsLg0KDQpgYGB7cn0NClBNX3dmbG93X2ZpdCA8LSBwYXJzbmlwOjpmaXQoUE1fd2Zsb3csIGRhdGEgPSB0cmFpbl9wbSkNClBNX3dmbG93X2ZpdA0KYGBgDQoNCg0KPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gc2VlIHRoZSBzdGVwcyB0aGF0IHRoZSBgd29ya2Zsb3dzYCBwYWNrYWdlIHBlcmZvcm1zIHRoYXQgdXNlZCB0byBiZSByZXF1aXJlZCA8L3N1bW1hcnk+DQoNClByZXZpb3VzbHksIHRoZSBwcm9jZXNzZWQgdHJhaW5pbmcgZGF0YSAoYGJha2VkX3RyYWluYCksIGFzIG9wcG9zZWQgdG8gdGhlIHJhdyB0cmFpbmluZyBkYXRhLCB3b3VsZCBiZSByZXF1aXJlZCB0byBmaXQgdGhlIG1vZGVsLg0KDQpJbiB0aGlzIGNhc2UsIHdlIHdvdWxkIGFjdHVhbGx5IGFsc28gbmVlZCB0byB3cml0ZSB0aGUgbW9kZWwgYWdhaW4hIA0KUmVjYWxsIHRoYXQgYGlkYCBhbmQgYGZpcHNgIGFyZSBJRCB2YXJpYWJsZXMgYW5kIHRoYXQgYHZhbHVlc2AgaXMgb3VyIG91dGNvbWUgb2YgaW50ZXJlc3QgKHRoZSBhaXIgcG9sbHV0aW9uIG1lYXN1cmUgYXQgZWFjaCBtb25pdG9yKS4gSXQgaXMgbmljZSB0aGF0IGB3b3JrZmxvd3NgIGtlZXBzIHRyYWNrIG9mIHRoaXMhDQoNCmBgYHtyfQ0KYmFrZWRfdHJhaW5fcmVhZHkgPC0gYmFrZWRfdHJhaW4gJT4lIA0KICBzZWxlY3QoLWlkLCAtZmlwcykNCg0KUE1fZml0IDwtIGxtX1BNX21vZGVsICU+JSANCiAgcGFyc25pcDo6Zml0KHZhbHVlIH4uLCBkYXRhID0gYmFrZWRfdHJhaW5fcmVhZHkpDQpgYGANCg0KPC9kZXRhaWxzPg0KDQojIyAqKkFzc2Vzc2luZyB0aGUgbW9kZWwgZml0KioNCioqKg0KDQpBZnRlciB3ZSBmaXQgb3VyIG1vZGVsLCB3ZSBjYW4gdXNlIHRoZSBgYnJvb21gIHBhY2thZ2UgdG8gbG9vayBhdCB0aGUgb3V0cHV0IGZyb20gdGhlIGZpdHRlZCBtb2RlbCBpbiBhbiBlYXN5L3RpZHkgd2F5LiAgIA0KDQpUaGUgYHRpZHkoKWAgZnVuY3Rpb24gcmV0dXJucyBhIHRpZHkgZGF0YSBmcmFtZSB3aXRoIGNvZWZmaWNpZW50cyBmcm9tIHRoZSBtb2RlbCAob25lIHJvdyBwZXIgY29lZmZpY2llbnQpLg0KDQpNYW55IG90aGVyIGBicm9vbWAgZnVuY3Rpb25zIGN1cnJlbnRseSBvbmx5IHdvcmsgd2l0aCBgcGFyc25pcGAgb2JqZWN0cywgbm90IHJhdyBgd29ya2Zsb3dzYCBvYmplY3RzLiANCg0KSG93ZXZlciwgd2UgY2FuIHVzZSB0aGUgYHRpZHlgIGZ1bmN0aW9uIGlmIHdlIGZpcnN0IHVzZSB0aGUgYHB1bGxfd29ya2Zsb3dfZml0KClgIGZ1bmN0aW9uLg0KDQpgYGB7cn0NCndmbG93b3V0cHV0IDwtIFBNX3dmbG93X2ZpdCAlPiUgDQogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIA0KICBicm9vbTo6dGlkeSgpIA0KYGBgDQoNCg0KYGBge3J9DQp3Zmxvd291dHB1dA0KYGBgDQoNCldlIGhhdmUgZml0IG91ciBtb2RlbCBvbiBvdXIgdHJhaW5pbmcgZGF0YSwgd2hpY2ggbWVhbnMgd2UgaGF2ZSBjcmVhdGVkIGEgbW9kZWwgdG8gcHJlZGljdCB2YWx1ZXMgb2YgYWlyIHBvbGx1dGlvbiBiYXNlZCBvbiB0aGUgcHJlZGljdG9ycyB0aGF0IHdlIGhhdmUgaW5jbHVkZWQuIFlheSENCg0KT25lIGxhc3QgdGhpbmcgYmVmb3JlIHdlIGxlYXZlIHRoaXMgc2VjdGlvbi4gDQpXZSBvZnRlbiBhcmUgaW50ZXJlc3RlZCBpbiBnZXR0aW5nIGEgc2Vuc2Ugb2Ygd2hpY2ggdmFyaWFibGVzIGFyZSB0aGUgbW9zdCBpbXBvcnRhbnQgaW4gb3VyIG1vZGVsLiANCldlIGNhbiBleHBsb3JlIHRoZSB2YXJpYWJsZSBpbXBvcnRhbmNlIHVzaW5nIHRoZSBgdmlwKClgIGZ1bmN0aW9uIG9mIHRoZSBgdmlwYCBwYWNrYWdlLiANClRoaXMgZnVuY3Rpb24gY3JlYXRlcyBhIGJhciBwbG90IG9mIHZhcmlhYmxlIGltcG9ydGFuY2Ugc2NvcmVzIGZvciBlYWNoIHByZWRpY3RvciB2YXJpYWJsZSAob3IgZmVhdHVyZSkgaW4gYSBtb2RlbC4gDQpUaGUgYmFyIHBsb3QgaXMgb3JkZXJlZCBieSBpbXBvcnRhbmNlIChoaWdoZXN0IHRvIHNtYWxsZXN0KS4gDQoNCg0KTm90aWNlIGFnYWluIHRoYXQgd2UgbmVlZCB0byB1c2UgdGhlIGBwdWxsX3dvcmtmbG93X2ZpdCgpYCBmdW5jdGlvbi4NCg0KTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIHRvcCAxMCBjb250cmlidXRpbmcgdmFyaWFibGVzOg0KDQpgYGB7cn0NClBNX3dmbG93X2ZpdCAlPiUgDQogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIA0KICB2aXAobnVtX2ZlYXR1cmVzID0gMTApDQpgYGANCg0KVGhlIHN0YXRlIGluIHdoaWNoIHRoZSBtb25pdG9yIHdhcyBsb2NhdGVkIGFuZCB0aGUgQ01BUSBtb2RlbCBhbmQgdGhlIGFvZCBzYXRlbGxpdGUgaW5mb3JtYXRpb24gYXBwZWFyIHRvIGJlIHRoZSBtb3N0IGltcG9ydGFudCBmb3IgcHJlZGljdGluZyB0aGUgYWlyIHBvbGx1dGlvbiBhdCBhIGdpdmVuIG1vbml0b3IuDQoNCiMjICoqTW9kZWwgcGVyZm9ybWFuY2UqKg0KKioqDQoNCkluIHRoaXMgbmV4dCBzZWN0aW9uLCBvdXIgZ29hbCBpcyB0byBhc3Nlc3MgdGhlIG92ZXJhbGwgbW9kZWwgcGVyZm9ybWFuY2UuIA0KVGhlIHdheSB3ZSBkbyB0aGlzIGlzIHRvIGNvbXBhcmUgdGhlIHNpbWlsYXJpdHkgYmV0d2VlbiB0aGUgcHJlZGljdGVkIGVzdGltYXRlcyBvZiB0aGUgb3V0Y29tZSB2YXJpYWJsZSBwcm9kdWNlZCBieSB0aGUgbW9kZWwgYW5kIHRoZSB0cnVlIG91dGNvbWUgdmFyaWFibGUgdmFsdWVzLiANCg0KSWYgeW91IHJlY2FsbCB0aGUgW1doYXQgaXMgbWFjaGluZSBsZWFybmluZz9dKCN3aGF0aXNtbCkgc2VjdGlvbiwgd2Ugc2hvd2VkIGhvdyB0byB0aGluayBhYm91dCBtYWNoaW5lIGxlYXJuaW5nIChNTCkgYXMgYW4gb3B0aW1pemF0aW9uIHByb2JsZW0gdGhhdCB0cmllcyB0byBtaW5pbWl6ZSB0aGUgZGlzdGFuY2UgYmV0d2VlbiBvdXIgcHJlZGljdGVkIG91dGNvbWUgJFxoYXR7WX0gPSBmKFgpJCBhbmQgYWN0dWFsIG91dGNvbWUgJFkkIHVzaW5nIG91ciBmZWF0dXJlcyAob3IgcHJlZGljdG9yIHZhcmlhYmxlcykgJFgkIGFzIGlucHV0IHRvIGEgZnVuY3Rpb24gJGYkIHRoYXQgd2Ugd2FudCB0byBlc3RpbWF0ZS4gDQoNCiQkZChZIC0gXGhhdHtZfSkkJA0KDQpBcyBvdXIgZ29hbCBpbiB0aGlzIHNlY3Rpb24gaXMgdG8gYXNzZXNzIG92ZXJhbGwgbW9kZWwgcGVyZm9ybWFuY2UsIHdlIHdpbGwgbm93IHRhbGsgYWJvdXQgZGlmZmVyZW50IGRpc3RhbmNlIG1ldHJpY3MgdGhhdCB5b3UgY2FuIHVzZS4gDQoNCkZpcnN0LCBsZXQncyBwdWxsIG91dCBvdXIgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzICRcaGF0e1l9ID0gZihYKSQgZnJvbSB0aGUgbW9kZWxzIHdlIGZpdCAodXNpbmcgZGlmZmVyZW50IGFwcHJvYWNoZXMpLiANCg0KDQpgYGB7cn0NCndmX2ZpdCA8LSBQTV93Zmxvd19maXQgJT4lIA0KICBwdWxsX3dvcmtmbG93X2ZpdCgpDQoNCndmX2ZpdHRlZF92YWx1ZXMgPC0gZml0dGVkKHdmX2ZpdFtbImZpdCJdXSkNCmhlYWQod2ZfZml0dGVkX3ZhbHVlcykNCmBgYA0KDQpBbHRlcm5hdGl2ZWx5LCB3ZSBjYW4gZ2V0IHRoZSBmaXR0ZWQgdmFsdWVzIHVzaW5nIHRoZSBgYXVnbWVudCgpYCBmdW5jdGlvbiBvZiB0aGUgYGJyb29tYCBwYWNrYWdlIHVzaW5nIHRoZSBvdXRwdXQgZnJvbSBgd29ya2Zsb3dzYDogDQoNCmBgYHtyfQ0Kd2ZfZml0dGVkX3ZhbHVlcyA8LSANCiAgYnJvb206OmF1Z21lbnQod2ZfZml0W1siZml0Il1dLCBkYXRhID0gYmFrZWRfdHJhaW4pICU+JSANCiAgc2VsZWN0KHZhbHVlLCAuZml0dGVkOi5zdGQucmVzaWQpDQoNCmhlYWQod2ZfZml0dGVkX3ZhbHVlcykNCg0KYGBgDQoNCk5vdGUgdGhhdCBiZWN1YXNlIHdlIHVzZSB0aGUgYWN0dWFsIHdvcmtmbG93IGhlcmUsIHdlIGNhbiAoYW5kIGFjdHVhbGx5IG5lZWQgdG8pIHVzZSB0aGUgcmF3IGRhdGEgaW5zdGVhZCBvZiB0aGUgcHJlLXByb2Nlc3NlZCBkYXRhLg0KDQpgYGB7cn0NCnZhbHVlc19wcmVkX3RyYWluIDwtIA0KICBwcmVkaWN0KFBNX3dmbG93X2ZpdCwgdHJhaW5fcG0pICU+JSANCiAgYmluZF9jb2xzKHRyYWluX3BtICU+JSBzZWxlY3QodmFsdWUsIGZpcHMsIGNvdW50eSwgaWQpKSANCg0KdmFsdWVzX3ByZWRfdHJhaW4NCg0KYGBgDQoNCiMjIyAqKlZpc3VhbGl6aW5nIG1vZGVsIHBlcmZvcm1hbmNlKioNCioqKg0KDQpOb3csIHdlIGNhbiBjb21wYXJlIHRoZSBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgKG9yIGZpdHRlZCB2YWx1ZXMpICRcaGF0e1l9JCB0byB0aGUgYWN0dWFsIG91dGNvbWUgdmFsdWVzICRZJCB0aGF0IHdlIG9ic2VydmVkOiANCg0KYGBge3J9DQp3Zl9maXR0ZWRfdmFsdWVzICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gIHZhbHVlLCB5ID0gLmZpdHRlZCkpICsgDQogIGdlb21fcG9pbnQoKSArIA0KICB4bGFiKCJhY3R1YWwgb3V0Y29tZSB2YWx1ZXMiKSArIA0KICB5bGFiKCJwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMiKQ0KYGBgDQoNCk9LLCBzbyBvdXIgcmFuZ2Ugb2YgdGhlIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcyBhcHBlYXJzIHRvIGJlIHNtYWxsZXIgdGhhbiB0aGUgcmVhbCB2YWx1ZXMuIA0KV2UgY291bGQgcHJvYmFibHkgZG8gYSBiaXQgYmV0dGVyLg0KDQojIyMgKipRdWFudGlmeWluZyBtb2RlbCBwZXJmb3JtYW5jZSoqDQoqKioNCg0KTmV4dCwgbGV0J3MgdXNlIGRpZmZlcmVudCBkaXN0YW5jZSBmdW5jdGlvbnMgJGQoXGNkb3QpJCB0byBhc3Nlc3MgaG93IGZhciBvZmYgb3VyIHByZWRpY3RlZCBvdXRjb21lICRcaGF0e1l9ID0gZihYKSQgYW5kIGFjdHVhbCBvdXRjb21lICRZJCB2YWx1ZXMgYXJlIGZyb20gZWFjaCBvdGhlcjogDQoNCiQkZChZIC0gXGhhdHtZfSkkJA0KDQpBcyBtZW50aW9uZWQsIHRoZXJlIGFyZSBlbnRpcmUgc2Nob2xhcmx5IGZpZWxkcyBvZiByZXNlYXJjaCBkZWRpY2F0ZWQgdG8gaWRlbnRpZnlpbmcgZGlmZmVyZW50IGRpc3RhbmNlIG1ldHJpY3MgJGQoXGNkb3QpJCBmb3IgbWFjaGluZSBsZWFybmluZyBhcHBsaWNhdGlvbnMuIA0KSG93ZXZlciwgd2hlbiBwZXJmb3JtaW5nIHByZWRpY3Rpb24gd2l0aCBhIGNvbnRpbnVvdXMgb3V0Y29tZSAkWSQsIGEgZmV3IG9mIHRoZSBtb3N0bHkgY29tbW9ubHkgdXNlZCBkaXN0YW5jZSBtZXRyaWNzIGFyZTogDQoNCjEuIG1lYW4gYWJzb2x1dGUgZXJyb3IgKGBtYWVgKSAgDQoNCiQkTUFFID0gXGZyYWN7XHN1bV97aT0xfV57bn17KHxcaGF0e3lfdH0tIHlfdHwpfV4yfXtufSQkDQoNCg0KMi4gUiBzcXVhcmVkIGVycm9yIChgcnNxYCkgLS0gdGhpcyBpcyBhbHNvIGtub3duIGFzIHRoZSBjb2VmZmljaWVudCBvZiBkZXRlcm1pbmF0aW9uIHdoaWNoIGlzIHRoZSBzcXVhcmVkIGNvcnJlbGF0aW9uIGJldHdlZW4gdHJ1dGggYW5kIGVzdGltYXRlDQoNClRoaXMgaXMgY2FsY3VsYXRlZCBhbmQgMSBtaW51cyB0aGUgZnJhY3Rpb24gb2YgdGhlIHJlc2lkdWFsIHN1bSBvZiBzcXVhcmVzICgkU1NfcmVzJCkgYnkgdGhlIHRvdGFsIHN1bSBvZiBzcXVhcmVzICgkU1NfdG90JCkNCg0KDQokJFJTUSA9IFJeMiA9IDEgLSBcZnJhY3tTU3Jlc317U1N0b3R9JCQNCg0KJCRTU197dG90fSA9IFxzdW1fe2k9MX1ee259eyh5X2ktIFxiYXJ7eX0pfV4yJCQNClRoZSB0b3RhbCBzdW0gb2Ygc3F1YXJlcyBpcyBwcm9wb3J0aW9uYWwgdG8gdGhlIHZhcmlhbmNlIG9mIHRoZSBkYXRhLiBJdCBpcyBjYWxjdWxhdGVkIGFzIHRoZSBzdW0gb2YgZWFjaCAgdHJ1ZSB2YWx1ZSBmcm9tIHRoZSBtZWFuIHRydWUgdmFsdWUgKCRcYmFye3l9JCkuDQoNCiQkU1Nfe3Jlc30gPSBcc3VtX3tpPTF9XntufXsoeV9pLSBcaGF0e3lfaX0pfV4yJCQNCg0KVGhlIHN1bSBvZiBzcXVhcmVzIG9mIHJlc2lkdWFscyBpcyBjYWxjdWxhdGVkIGFzIHRoZSBzdW0gb2YgZWFjaCBwcmVkaWN0ZWQgdmFsdWUgKCRcaGF0e3lfaX0kIG9yIHNvbWV0aW1lcyAkZl9pJCkgZnJvbSB0aGUgdHJ1ZSB2YWx1ZSAoJHlfaSQpLiANCg0KDQozLiBbcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3JdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Jvb3QtbWVhbi1zcXVhcmVfZGV2aWF0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9IChgcm1zZWApICAgDQoNCiQkUk1TRSA9IFxzcXJ0e1xmcmFje1xzdW1fe2k9MX1ee259eyhcaGF0e3lfdH0tIHlfdCl9XjJ9e259fSQkDQoNCg0KDQoNCk9uZSB3YXkgdG8gY2FsY3VsYXRlIHRoZXNlIG1ldHJpY3Mgd2l0aGluIHRoZSBgdGlkeW1vZGVsc2AgZnJhbWV3b3JrIGlzIHRvIHVzZSB0aGUgYHlhcmRzdGlja2AgcGFja2FnZSB1c2luZyB0aGUgYG1ldHJpY3MoKWAgZnVuY3Rpb24uIA0KDQpgYGB7cn0NCnlhcmRzdGljazo6bWV0cmljcyh3Zl9maXR0ZWRfdmFsdWVzLCANCiAgICAgICAgICAgICAgICAgICB0cnV0aCA9IHZhbHVlLCBlc3RpbWF0ZSA9IC5maXR0ZWQpDQpgYGANCg0KQWx0ZXJuYXRpdmVseSBpZiB5b3Ugb25seSB3YW50ZWQgb25lIG1ldHJpYyB5b3UgY291bGQgdXNlIHRoZSBgbWFlKClgLCBgcnNxKClgLCBvciBgcm1zZSgpYCBmdW5jdGlvbnMsIHJlc3BlY3RpdmVseS4gDQoNCmBgYHtyfQ0KeWFyZHN0aWNrOjptYWUod2ZfZml0dGVkX3ZhbHVlcywgDQogICAgICAgICAgICAgICB0cnV0aCA9IHZhbHVlLCBlc3RpbWF0ZSA9IC5maXR0ZWQpDQpgYGANCg0KIyMgKipDcm9zcyB2YWxpZGF0aW9uKioNCioqKg0KDQpVbnRpbCBub3cgd2UgaGF2ZSB1c2VkIGV2ZXJ5dGhpbmcgaW4gb3VyICJ0cmFpbmluZyIgZGF0YXNldCAoYW5kIGhhdmUgbm90IHRvdWNoZWQgdGhlICJ0ZXN0aW5nIiBkYXRhc2V0KSBmcm9tIHRoZSBgcnNhbXBsZWAgcGFja2FnZSB0byBidWlsZCBvdXIgbWFjaGluZSBsZWFybmluZyAoTUwpIG1vZGVsICRcaGF0e1l9ID0gZihYKSQgKG9yIHRvIGVzdGltYXRlICRmJCB1c2luZyB0aGUgZmVhdHVyZXMgb3IgcHJlZGljdG9yIHZhcmlhYmxlICRYJCkuIA0KDQpIZXJlLCB3ZSB0YWtlIG1vdmUgdGhpcyBiZXlvbmQgdGhlIHNpbXBsZSBzcGxpdCBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0aW5nIGRhdGEgc2V0cy4gDQpXZSB3aWxsIGFnYWluIHVzZSB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgYWdhaW4gaW4gb3JkZXIgdG8gZnVydGhlciBpbXBsZW1lbnQgd2hhdCBhcmUgY2FsbGVkIFtjcm9zcyB2YWxpZGF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Dcm9zcy12YWxpZGF0aW9uXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSB0ZWNobmlxdWVzLiBUaGlzIGlzIGFsc28gY2FsbGVkICoqcmUtc2FtcGxpbmcqKiBvciAqKnJlcGFydGlvbmluZyoqLiAgDQoNCioqTm90ZSoqOiB3ZSBhcmUgbm90IGFjdHVhbGx5IGdldHRpbmcgbmV3IHNhbXBsZXMgZnJvbSB0aGUgdW5kZXJseWluZyBkaXN0cmlidXRpb24gc28gdGhlIHRlcm0gcmUtc2FtcGxpbmcgaXMgYSBiaXQgb2YgYSBtaXNub21lci4NCg0KW0Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IHNwbGl0cyBvdXIgdHJhaW5pbmcgZGF0YSBpbnRvIG11bHRpcGxlIHRyYWluaW5nIGRhdGEgc2V0cyB0byBhbGxvdyBmb3IgYSBkZWVwZXIgYXNzZXNzbWVudCBvZiB0aGUgYWNjdXJhY3kgb2YgdGhlIG1vZGVsLg0KDQpIZXJlIGlzIGEgdmlzdWFsaXphdGlvbiBvZiB0aGUgY29uY2VwdCBmb3IgY3Jvc3MgdmFsaWRhdGlvbi9yZXNhbXBsaW5nL3JlcGFydGl0aW9uaW5nIGZyb20gW01heCBLdWhuXShodHRwczovL3Jlc291cmNlcy5yc3R1ZGlvLmNvbS9hdXRob3JzL21heC1rdWhuKXt0YXJnZXQ9Il9ibGFuayJ9Og0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJyZXNhbXBsaW5nLnBuZyIpKQ0KYGBgDQoNClRlY2huaWNhbGx5IGNyZWF0aW5nIG91ciB0ZXN0aW5nIGFuZCB0cmFpbmluZyBzZXQgb3V0IG9mIG91ciBvcmlnaW5hbCB0cmFpbmluZyBkYXRhIGlzIHNvbWV0aW1lcyBjb25zaWRlcmVkIGEgZm9ybSBvZiBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0sIGNhbGxlZCB0aGUgaG9sZG91dCBtZXRob2QuIA0KVGhlIHJlYXNvbiB3ZSBkbyB0aGlzIGl0IHNvIHdlIGNhbiBnZXQgYSBiZXR0ZXIgc2Vuc2Ugb2YgdGhlIGFjY3VyYWN5IG9mIG91ciBtb2RlbCB1c2luZyBkYXRhIHRoYXQgd2UgZGlkIG5vdCB0cmFpbiBpdCBvbi4gDQoNCkhvd2V2ZXIsIHdlIGNhbiBhY3R1YWxseSBkbyBhIGJldHRlciBqb2Igb2Ygb3B0aW1pemluZyBvdXIgbW9kZWwgZm9yIGFjY3VyYWN5IGlmIHdlIGFsc28gcGVyZm9ybSBhbm90aGVyIHR5cGUgb2YgW2Nyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXZhbGlkYXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9IG9uIHRoZSBuZXdseSBkZWZpbmVkIHRyYWluaW5nIHNldCB0aGF0IHdlIGp1c3QgY3JlYXRlZC4gDQpUaGVyZSBhcmUgbWFueSBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3Jvc3MtdmFsaWRhdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gbWV0aG9kcyBhbmQgbW9zdCBjYW4gYmUgZWFzaWx5IGltcGxlbWVudGVkIHVzaW5nIGByc2FtcGxlYCBwYWNrYWdlLiANCkhlcmUsIHdlIHdpbGwgdXNlIGEgdmVyeSBwb3B1bGFyIG1ldGhvZCBjYWxsZWQgZWl0aGVyIFtrLWZvbGQgb3Igdi1mb2xkIGNyb3NzIHZhbGlkYXRpb25dKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vay1mb2xkLWNyb3NzLXZhbGlkYXRpb24vKXt0YXJnZXQ9Il9ibGFuayJ9LiANCg0KVGhpcyBtZXRob2QgaW52b2x2ZXMgZXNzZW50aWFsbHkgcHJlZm9ybWluZyB0aGUgaG9sZCBvdXQgbWV0aG9kIGl0ZXJhdGl2ZWx5IHdpdGggdGhlIHRyYWluaW5nIGRhdGEuIA0KDQpGaXJzdCwgdGhlIHRyYWluaW5nIHNldCBpcyBkaXZpZGVkIGludG8gJHYkIChvciBvZnRlbiBjYWxsZWQgY2FsbGVkICRrJCkgZXF1YWxseSBzaXplZCBzbWFsbGVyIHBpZWNlcy4gDQoNCk5leHQsIHRoZSBtb2RlbCBpcyB0cmFpbmVkIG9uIHRoZSBtb2RlbCBvbiAkdiQtMSBzdWJzZXRzIG9mIHRoZSBkYXRhIGl0ZXJhdGl2ZWx5IChyZW1vdmluZyBhIGRpZmZlcmVudCAkdiQgdW50aWwgYWxsIHBvc3NpYmxlICR2JC0xIHNldHMgaGF2ZSBiZWVuIGV2YWx1YXRlZCkgdG8gZ2V0IGEgc2Vuc2Ugb2YgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBtb2RlbC4gDQpUaGlzIGlzIHJlYWxseSB1c2VmdWwgZm9yIGZpbmUgdHVuaW5nIHNwZWNpZmljIGFzcGVjdHMgb2YgdGhlIG1vZGVsIGluIGEgcHJvY2VzcyBjYWxsZWQgbW9kZWwgdHVuaW5nLCB3aGljaCB3ZSB3aWxsIGxlYXJuIGFib3V0IGluIHRoZSBuZXh0IHNlY3Rpb24uIA0KDQpIZXJlIGlzIGEgdmlzdWFsaXphdGlvbiBvZiBob3cgdGhlIGZvbGRzIGFyZSBjcmVhdGVkOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidmZvbGQucG5nIikpDQpgYGANCg0KKipOb3RlKio6IFBlb3BsZSB0eXBpY2FsbHkgaWdub3JlIHNwYXRpYWwgZGVwZW5kZW5jZSB3aXRoIGNyb3NzIHZhbGlkYXRpb24gb2YgYWlyIHBvbGx1dGlvbiBtb25pdG9yaW5nIGRhdGEgaW4gdGhlIGFpciBwb2xsdXRpb24gZmllbGQsIHNvIHdlIHdpbGwgZG8gdGhlIHNhbWUuICBIb3dldmVyLCBpdCBtaWdodCBtYWtlIHNlbnNlIHRvIGxlYXZlIG91dCBibG9ja3Mgb2YgbW9uaXRvcnMgcmF0aGVyIHRoYW4gIHJhbmRvbSBpbmRpdmlkdWFsIG1vbml0b3JzIHRvIGhlbHAgYWNjb3VudCBmb3Igc29tZSBzcGF0aWFsIGRlcGVuZGVuY2UuDQoNCiMjIyAqKkNyZWF0aW5nIHRoZSAkdiQtZm9sZHMgdXNpbmcgYHJzYW1wbGVgKioNCioqKg0KDQpUaGUgW2B2Zm9sZF9jdigpYF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL3JlZmVyZW5jZS92Zm9sZF9jdi5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZ1bmN0aW9uIG9mIHRoZSBgcnNhbXBsZWAgcGFja2FnZSBjYW4gYmUgdXNlZCB0byBwYXJzZSB0aGUgdHJhaW5pbmcgZGF0YSBpbnRvIGZvbGRzIGZvciAkdiQtZm9sZCBjcm9zcyB2YWxpZGF0aW9uLg0KDQotIFRoZSBgdmAgYXJndW1lbnQgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgZm9sZHMgdG8gY3JlYXRlLg0KLSBUaGUgYHJlcGVhdHNgIGFyZ3VtZW50IHNwZWNpZmllcyBpZiBhbnkgc2FtcGxlcyBzaG91bGQgYmUgcmVwZWF0ZWQgYWNyb3NzIGZvbGRzIC0gZGVmYXVsdCBpcyBgRkFMU0VgDQotIFRoZSBgc3RyYXRhYCBhcmd1bWVudCBzcGVjaWZpZXMgYSB2YXJpYWJsZSB0byBzdHJhdGlmeSBzYW1wbGVzIGFjcm9zcyBmb2xkcyAtIGp1c3QgbGlrZSBpbiBgaW5pdGlhbF9zcGxpdCgpYC4NCg0KQWdhaW4sIGJlY2F1c2UgdGhlc2UgYXJlIGNyZWF0ZWQgYXQgcmFuZG9tLCB3ZSBuZWVkIHRvIHVzZSB0aGUgYmFzZSBgc2V0LnNlZWQoKWAgZnVuY3Rpb24gaW4gb3JkZXIgdG8gb2J0YWluIHRoZSBzYW1lIHJlc3VsdHMgZWFjaCB0aW1lIHdlIGtuaXQgdGhpcyBkb2N1bWVudC4gDQpHZW5lcmFsbHkgc3BlYWtpbmcgdXNpbmcgMTAgZm9sZHMgaXMgZ29vZCBwcmFjdGljZSwgYnV0IHRoaXMgZGVwZW5kcyBvbiB0aGUgdmFyaWFiaWxpdHkgd2l0aGluIHlvdXIgZGF0YS4gDQpXZSBhcmUgZ29pbmcgdG8gdXNlIDQgZm9yIHRoZSBzYWtlIG9mIGV4cGVkaWVuY3kuIA0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMzQpDQp2Zm9sZF9wbSA8LSByc2FtcGxlOjp2Zm9sZF9jdihkYXRhID0gdHJhaW5fcG0sIHYgPSA0KQ0KdmZvbGRfcG0NCnB1bGwodmZvbGRfcG0sIHNwbGl0cykNCmBgYA0KDQpOb3cgd2UgY2FuIHNlZSB0aGF0IHdlIGhhdmUgY3JlYXRlZCA0IGZvbGRzIG9mIHRoZSBkYXRhIGFuZCB3ZSBjYW4gc2VlIGhvdyBtYW55IHZhbHVlcyB3ZXJlIHNldCBhc2lkZSBmb3IgdGVzdGluZyAoY2FsbGVkIGFzc2Vzc2luZyBmb3IgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzKSBhbmQgdHJhaW5pbmcgKGNhbGxlZCBhbmFseXNpcyBmb3IgY3Jvc3MgdmFsaWRhdGlvbiBzZXRzKSB3aXRoaW4gZWFjaCBmb2xkLg0KDQpPbmNlIHRoZSBmb2xkcyBhcmUgY3JlYXRlZCB0aGV5IGNhbiBiZSB1c2VkIHRvIGV2YWx1YXRlIHBlcmZvcm1hbmNlIGJ5IGZpdHRpbmcgdGhlIG1vZGVsIHRvIGVhY2ggb2YgdGhlIHJlLXNhbXBsZXMgdGhhdCB3ZSBjcmVhdGVkOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiY3Jvc3NfdmFsaWRhdGlvbi5wbmciKSkNCmBgYA0KDQojIyMgKipBc3Nlc3NpbmcgbW9kZWwgcGVyZm9ybWFuY2Ugb24gJHYkLWZvbGRzIHVzaW5nIGB0dW5lYCoqDQoqKioNCg0KV2UgY2FuIGZpdCB0aGUgbW9kZWwgdG8gb3VyIGNyb3NzIHZhbGlkYXRpb24gZm9sZHMgdXNpbmcgdGhlIGBmaXRfcmVzYW1wbGVzKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSwgYnkgc3BlY2lmeWluZyBvdXIgYHdvcmtmbG93YCBvYmplY3QgYW5kIHRoZSBjcm9zcyB2YWxpZGF0aW9uIGZvbGQgb2JqZWN0IHdlIGp1c3QgY3JlYXRlZC4gDQpTZWUgW2hlcmVdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vdHVuZS9yZWZlcmVuY2UvZml0X3Jlc2FtcGxlcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uLg0KDQoNCmBgYHtyfQ0KcmVzYW1wbGVfZml0IDwtIHR1bmU6OmZpdF9yZXNhbXBsZXMoUE1fd2Zsb3csIHZmb2xkX3BtKQ0KYGBgDQoNCldlIGNhbiBub3cgdGFrZSBhIGxvb2sgYXQgdmFyaW91cyBwZXJmb3JtYW5jZSBtZXRyaWNzIGJhc2VkIG9uIHRoZSBmaXQgb2Ygb3VyIGNyb3NzIHZhbGlkYXRpb24gInJlc2FtcGxlcyIuIA0KVG8gZG8gdGhpcyB3ZSB3aWxsIHVzZSB0aGUgYHNob3dfYmVzdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UuDQoNCmBgYHtyfQ0KdHVuZTo6c2hvd19iZXN0KHJlc2FtcGxlX2ZpdCwgbWV0cmljID0gInJtc2UiKQ0KYGBgDQoNCkhlcmUgd2UgY2FuIHNlZSB0aGUgbWVhbiBgUk1TRWAgdmFsdWUgYWNyb3NzIGFsbCBmb3VyIGZvbGRzLiBUaGUgZnVuY3Rpb24gaXMgY2FsbGVkIGBzaG93X2Jlc3QoKWAgYmVjYXVzZSBpdCBpcyBhbHNvIHVzZWQgZm9yIG1vZGVsIHR1bmluZyBhbmQgaXQgd2lsbCBzaG93IHRoZSBwYXJhbWV0ZXIgY29tYmluYXRpb24gd2l0aCB0aGUgYmVzdCBwZXJmb3JtYW5jZSwgd2Ugd2lsbCBkaXNjdXNzIHRoaXMgbW9yZSBsYXRlciBpbiB0aGUgY2FzZSBzdHVkeS4NCg0KDQojICoqRGF0YSBBbmFseXNpcyoqDQoqKioNCg0KSW4gdGhlIHByZXZpb3VzIHNlY3Rpb24sIHdlIGRlbW9uc3RyYXRlZCBob3cgdG8gYnVpbGQgYSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVsIChzcGVjaWZpY2FsbHkgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCkgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIHdpdGggdGhlIGB0aWR5bW9kZWxzYCBmcmFtZXdvcmsuIA0KDQpJbiB0aGUgbmV4dCBmZXcgc2VjdGlvbiwgd2Ugd2lsbCBkZW1vbnN0cmF0ZSBhbm90aGVyIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwuIA0KDQoNCiMjICoqUmFuZG9tIEZvcmVzdCoqDQoqKioNCg0KTm93LCB3ZSBhcmUgZ29pbmcgdG8gcHJlZGljdCBvdXIgb3V0Y29tZSB2YXJpYWJsZSAoYWlyIHBvbGx1dGlvbikgdXNpbmcgYSBkZWNpc2lvbiB0cmVlIG1ldGhvZCBjYWxsZWQgW3JhbmRvbSBmb3Jlc3RdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JhbmRvbV9mb3Jlc3Qpe3RhcmdldD0iX2JsYW5rIn0uDQoNCkEgW2RlY2lzaW9uIHRyZWVdKGh0dHBzOi8vbWVkaXVtLmNvbS9ncmV5YXRvbS9kZWNpc2lvbi10cmVlcy1hLXNpbXBsZS13YXktdG8tdmlzdWFsaXplLWEtZGVjaXNpb24tZGM1MDZhNDAzYWViKXt0YXJnZXQ9Il9ibGFuayJ9IGlzIGEgdG9vbCB0byBwYXJ0aXRpb24gZGF0YSBvciBhbnl0aGluZyByZWFsbHksIGJhc2VkIG9uIGEgc2VyaWVzIG9mIHNlcXVlbnRpYWwgKG9mdGVuIGJpbmFyeSkgZGVjaXNpb25zLCB3aGVyZSB0aGUgZGVjaXNpb25zIGFyZSBjaG9zZW4gYmFzZWQgb24gdGhlaXIgYWJpbGl0eSB0byBvcHRpbWFsbHkgc3BsaXQgdGhlIGRhdGEuDQoNCkhlcmUgeW91IGNhbiBzZWUgYSBzaW1wbGUgZXhhbXBsZToNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL21pcm8ubWVkaXVtLmNvbS9tYXgvMTAwMC8xKkxNb0ptWENzUWxjaUdURXlvU04zOWcuanBlZyIpDQpgYGANCg0KIyMjIyMgW1tzb3VyY2VdXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vdW5kZXJzdGFuZGluZy1yYW5kb20tZm9yZXN0LTU4MzgxZTA2MDJkMil7dGFyZ2V0PSJfYmxhbmsifQ0KDQpJbiB0aGUgY2FzZSBvZiBbcmFuZG9tIGZvcmVzdF0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL2RlY2lzaW9uLXRyZWUtZW5zZW1ibGVzLWJhZ2dpbmctYW5kLWJvb3N0aW5nLTI2NmE4YmE2MGZkOSl7dGFyZ2V0PSJfYmxhbmsifSwgbXVsdGlwbGUgZGVjaXNpb24gdHJlZXMgYXJlIGNyZWF0ZWQgLSBoZW5jZSB0aGUgbmFtZSBmb3Jlc3QsIGFuZCBlYWNoIHRyZWUgaXMgYnVpbHQgdXNpbmcgYSByYW5kb20gc3Vic2V0IG9mIHRoZSB0cmFpbmluZyBkYXRhICh3aXRoIHJlcGxhY2VtZW50KSAtIGhlbmNlIHRoZSBmdWxsIG5hbWUgcmFuZG9tIGZvcmVzdC4gVGhpcyByYW5kb20gYXNwZWN0IGhlbHBzIHRvIGtlZXAgdGhlIGFsZ29yaXRobSBmcm9tIG92ZXJmaXR0aW5nIHRoZSBkYXRhLg0KDQpUaGUgbWVhbiBvZiB0aGUgcHJlZGljdGlvbnMgZnJvbSBlYWNoIG9mIHRoZSB0cmVlcyBpcyB1c2VkIGluIHRoZSBmaW5hbCBvdXRwdXQuDQoNCmBgYHtyLCBlY2hvID0gRkFMU0V9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vbWF4LzE0MDAvMCpmX3FRUEZwZG9mV0dMUXFjLnBuZyIpDQpgYGANCg0KDQpJbiBvdXIgY2FzZSwgd2UgYXJlIGdvaW5nIHRvIHVzZSB0aGUgcmFuZG9tIGZvcmVzdCBtZXRob2Qgb2YgdGhlIHRoZSBgcmFuZG9tRm9yZXN0YCBwYWNrYWdlLiANCg0KVGhpcyBwYWNrYWdlIGlzIGN1cnJlbnRseSBub3QgY29tcGF0aWJsZSB3aXRoIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB0aGF0IGhhdmUgbW9yZSB0aGFuIDUzIGxldmVscy4gU2VlIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L05FV1MpIGZvciB0aGUgZG9jdW1lbnRhdGlvbiBhYm91dCB3aGVuIHRoaXMgd2FzIHVwZGF0ZWQgZnJvbSAyNSBsZXZlbHMuIFRodXMgd2Ugd2lsbCByZW1vdmUgdGhlIGB6Y3RhYCAgYW5kIGBjb3VudHlgIHZhcmlhYmxlcy4NCg0KTm90ZSB0aGF0IHRoZSBgc3RlcF9ub3ZlbCgpYCBmdW5jdGlvbiBpcyBuZWNlc3NhcnkgaGVyZSBmb3IgdGhlIGBzdGF0ZWAgdmFyaWFibGUgdG8gZ2V0IGFsbCBjcm9zcyB2YWxpZGF0aW9uIGZvbGRzIHRvIHdvcmssIGJlY2F1c2UgdGhlcmUgd2lsbCBiZSBkaWZmZXJlbnQgbGV2ZWxzIGluY2x1ZGVkIGluIGVhY2ggZm9sZCB0ZXN0IGFuZCB0cmFpbmluZyBzZXRzLiBUaGUgbmV3IGxldmVscyBmb3Igc29tZSBvZiB0aGUgdGVzdCBzZXRzIHdvdWxkIG90aGVyd2lzZSByZXN1bHQgaW4gYW4gZXJyb3IuDQoNCkFjY29yZGluZyB0byB0aGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy9yZWNpcGVzL3ZlcnNpb25zLzAuMS4xMy90b3BpY3Mvc3RlcF9ub3ZlbCkgZm9yIHRoZSBgcmVjaXBlc2AgcGFja2FnZToNCg0KPiBzdGVwX25vdmVsIGNyZWF0ZXMgYSBzcGVjaWZpY2F0aW9uIG9mIGEgcmVjaXBlIHN0ZXAgdGhhdCB3aWxsIGFzc2lnbiBhIHByZXZpb3VzbHkgdW5zZWVuIGZhY3RvciBsZXZlbCB0byBhIG5ldyB2YWx1ZS4NCg0KYGBge3J9DQpSRl9yZWMgPC0gcmVjaXBlKHRyYWluX3BtKSAlPiUNCiAgICB1cGRhdGVfcm9sZShldmVyeXRoaW5nKCksIG5ld19yb2xlID0gInByZWRpY3RvciIpJT4lDQogICAgdXBkYXRlX3JvbGUodmFsdWUsIG5ld19yb2xlID0gIm91dGNvbWUiKSU+JQ0KICAgIHVwZGF0ZV9yb2xlKGlkLCBuZXdfcm9sZSA9ICJpZCB2YXJpYWJsZSIpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKCJmaXBzIiwgbmV3X3JvbGUgPSAiY291bnR5IGlkIikgJT4lDQogICAgc3RlcF9ub3ZlbCgic3RhdGUiKSAlPiUNCiAgICBzdGVwX3N0cmluZzJmYWN0b3IoInN0YXRlIiwgImNvdW50eSIsICJjaXR5IikgJT4lDQogICAgc3RlcF9ybSgiY291bnR5IikgJT4lDQogICAgc3RlcF9ybSgiemN0YSIpICU+JQ0KICAgIHN0ZXBfY29ycihhbGxfbnVtZXJpYygpKSU+JQ0KICAgIHN0ZXBfbnp2KGFsbF9udW1lcmljKCkpDQpgYGANCg0KVGhlIGByYW5kX2ZvcmVzdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHBhcnNuaXBgIHBhY2thZ2UgaGFzIHRocmVlIGltcG9ydGFudCBhcmd1bWVudHMgdGhhdCBhY3QgYXMgYW4gaW50ZXJmYWNlIGZvciB0aGUgZGlmZmVyZW50IHBvc3NpYmxlIGVuZ2luZXMgdG8gcGVyZm9ybSBhIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXM6DQoNCjEuIGBtdHJ5YCAtIFRoZSBudW1iZXIgb2YgcHJlZGljdG9yIHZhcmlhYmxlcyAob3IgZmVhdHVyZXMpIHRoYXQgd2lsbCBiZSByYW5kb21seSBzYW1wbGVkIGF0IGVhY2ggc3BsaXQgd2hlbiBjcmVhdGluZyB0aGUgdHJlZSBtb2RlbHMuIFRoZSBkZWZhdWx0IG51bWJlciBmb3IgcmVncmVzc2lvbiBhbmFseXNlcyBpcyB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgZGl2aWRlZCBieSAzLiANCjIuIGBtaW5fbmAgLSBUaGUgbWluaW11bSBudW1iZXIgb2YgZGF0YSBwb2ludHMgaW4gYSBub2RlIHRoYXQgYXJlIHJlcXVpcmVkIGZvciB0aGUgbm9kZSB0byBiZSBzcGxpdCBmdXJ0aGVyLg0KMy4gYHRyZWVzYCAtIHRoZSBudW1iZXIgb2YgdHJlZXMgaW4gdGhlIGVuc2VtYmxlDQoNCldlIHdpbGwgc3RhcnQgYnkgdHJ5aW5nIGFuIGBtdHJ5YCB2YWx1ZSBvZiAxMCBhbmQgYSBgbWluX25gIHZhbHVlIG9mIDMuDQoNCk5vdyB0aGF0IHdlIGhhdmUgb3VyIHJlY2lwZSAoYFJGX3JlY2ApLCBsZXQncyBzcGVjaWZ5IHRoZSBtb2RlbCB3aXRoIGByYW5kX2ZvcmVzdCgpYCBmcm9tIGBwYXJzbmlwYC4NCg0KYGBge3J9DQpQTXRyZWVfbW9kZWwgPC0gDQogIHBhcnNuaXA6OnJhbmRfZm9yZXN0KG10cnkgPSAxMCwgbWluX24gPSAzKQ0KUE10cmVlX21vZGVsDQpgYGANCg0KTmV4dCwgd2Ugc2V0IHRoZSBlbmdpbmUgYW5kIG1vZGU6DQoNCk5vdGUgdGhhdCB5b3UgY291bGQgYWxzbyB1c2UgdGhlIGByYW5nZXJgIG9yIGBzcGFya2AgcGFja2FnZXMgaW5zdGVhZCBvZiBgcmFuZG9tRm9yZXN0YC4NCklmIHlvdSB3ZXJlIHRvIHVzZSB0aGUgYHJhbmdlcmAgcGFja2FnZSB0byBpbXBsZW1lbnQgdGhlIHJhbmRvbSBmb3Jlc3QgYW5hbHlzaXMgeW91IHdvdWxkIG5lZWQgdG8gc3BlY2lmeSBhbiBgaW1wb3J0YW5jZWAgYXJndW1lbnQgdG8gYmUgYWJsZSB0byBldmFsdWF0ZSBwcmVkaWN0b3IgaW1wb3J0YW5jZS4gIFRoZSBvcHRpb25zIGFyZSBgaW1wdXJpdHlgIG9yIGBwZXJtdXRhdGlvbmAuDQoNClRoZXNlIG90aGVyIHBhY2thZ2VzIGhhdmUgZGlmZmVyZW50IGFkdmFudGFnZXMgYW5kIGRpc2FkdmFudGFnZXMtIGZvciBleGFtcGxlIGByYW5nZXJgIGFuZCBgc3BhcmtgIGFyZSBub3QgYXMgbGltaXRpbmcgZm9yIHRoZSBudW1iZXIgb2YgY2F0ZWdvcmllcyBmb3IgY2F0ZWdvcmljYWwgdmFyaWFibGVzLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBzZWUgdGhlaXIgZG9jdW1lbnRhdGlvbjogW2hlcmVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yYW5nZXIvcmFuZ2VyLnBkZikgZm9yIHJhbmdlciwgW2hlcmVdKGh0dHA6Ly9zcGFyay5hcGFjaGUub3JnL2RvY3MvbGF0ZXN0L21sbGliLWVuc2VtYmxlcy5odG1sI3JhbmRvbS1mb3Jlc3RzKSBmb3IgYHNwYXJrYCwgYW5kIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpIGZvciBgcmFuZG9tRm9yZXN0YC4NCg0KU2VlIFtoZXJlXShodHRwczovL3BhcnNuaXAudGlkeW1vZGVscy5vcmcvcmVmZXJlbmNlL3JhbmRfZm9yZXN0Lmh0bWwpIGZvciBtb3JlIGRvY3VtZW50YXRpb24gYWJvdXQgaW1wbGVtZW50aW5nIHRoZXNlIGVuZ2luZSBvcHRpb25zIHdpdGggdGlkeW1vZGVscy4gTm90ZSB0aGF0IHRoZXJlIGFyZSBhbHNvIFtvdGhlcl0oaHR0cHM6Ly93d3cubGlua2VkaW4uY29tL3B1bHNlL2RpZmZlcmVudC1yYW5kb20tZm9yZXN0LXBhY2thZ2VzLXItbWFkaHVyLW1vZGkvKSBSIHBhY2thZ2VzIGZvciBpbXBsZW1lbnRpbmcgcmFuZG9tIGZvcmVzdCBhbGdvcml0aG1zLCBidXQgdGhlc2UgdGhyZWUgcGFja2FnZXMgKGByYW5nZXJgLCBgc3BhcmtgLCBhbmQgYHJhbmRvbUZvcmVzdGApIGFyZSBjdXJyZW50bHkgY29tcGF0aWJsZSB3aXRoIGB0aWR5bW9kZWxzYC4NCg0KV2UgYWxzbyBuZWVkIHRvIHNwZWNpZnkgd2l0aCB0aGUgYHNldF9tb2RlKClgIGZ1bmN0aW9uIHRoYXQgb3VyIG91dGNvbWUgdmFyaWFibGUgKGFpciBwb2xsdXRpb24pIGlzIGNvbnRpbnVvdXMuIA0KDQpgYGB7cn0NCg0KUkZfUE1fbW9kZWwgPC0gDQogIFBNdHJlZV9tb2RlbCAlPiUNCiAgc2V0X2VuZ2luZSgicmFuZG9tRm9yZXN0IikgJT4lDQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikNCg0KUkZfUE1fbW9kZWwNCmBgYA0KDQpUaGVuLCB3ZSBwdXQgdGhpcyBhbGwgdG9nZXRoZXIgaW50byBhIGB3b3JrZmxvd2A6IA0KDQojIyMjIHsucmVjYWxsX2NvZGVfcXVlc3Rpb25fYmxvY2t9DQo8Yj48dT4gUXVlc3Rpb24gT3Bwb3J0dW5pdHkgPC91PjwvYj4NCg0KU2VlIGlmIHlvdSBjYW4gY29tZSB1cCB3aXRoIHRoZSBjb2RlIHRvIGRvIHRoaXMuDQoNCiMjIyMNCg0KKioqDQo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4NCg0KYGBge3J9DQpSRl93ZmxvdyA8LSB3b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lDQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoUkZfcmVjKSAlPiUNCiAgICAgICAgICAgIHdvcmtmbG93czo6YWRkX21vZGVsKFJGX1BNX21vZGVsKQ0KDQpgYGANCjwvZGV0YWlscz4gDQoqKioNCg0KYGBge3J9DQpSRl93Zmxvdw0KYGBgDQoNCg0KRmluYWxseSwgd2UgZml0IHRoZSBkYXRhIHRvIHRoZSBtb2RlbDoNCg0KIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQ0KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+DQoNCkRvIHlvdSByZWNhbGwgaG93IHRvIGRvIHRoaXM/DQoNCiMjIyMNCg0KKioqDQo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4NCg0KYGBge3J9DQpSRl93Zmxvd19maXQgPC0gcGFyc25pcDo6Zml0KFJGX3dmbG93LCBkYXRhID0gdHJhaW5fcG0pDQpgYGANCjwvZGV0YWlscz4gDQoqKioNCg0KYGBge3J9DQpSRl93Zmxvd19maXQNCmBgYA0KDQpMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgdG9wIDEwIGNvbnRyaWJ1dGluZyB2YXJpYWJsZXM6DQoNCiMjIyMgey5yZWNhbGxfY29kZV9xdWVzdGlvbl9ibG9ja30NCjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPg0KDQpTZWUgaWYgeW91IGNhbiByZWNhbGwgaG93IHRvIGRvIHRoaXMuDQoNCiMjIyMNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NClJGX3dmbG93X2ZpdCAlPiUgDQogIHB1bGxfd29ya2Zsb3dfZml0KCkgJT4lIA0KICB2aXAobnVtX2ZlYXR1cmVzID0gMTApDQoNCmBgYA0KDQoNCioqKg0KPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIHRvIHJldmVhbCB0aGUgYW5zd2VyLiA8L3N1bW1hcnk+DQoNCmBgYHtyfQ0KUkZfd2Zsb3dfZml0ICU+JSANCiAgcHVsbF93b3JrZmxvd19maXQoKSAlPiUgDQogIHZpcChudW1fZmVhdHVyZXMgPSAxMCkNCmBgYA0KPC9kZXRhaWxzPg0KKioqDQoNCg0KSW50ZXJlc3RpbmchIEluIHRoZSBwcmV2aW91cyBtb2RlbCB0aGUgQ01BUSB2YWx1ZXMgYW5kIHRoZSBzdGF0ZSB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCB3ZXJlIGFsc28gdGhlIHRvcCB0d28gbW9zdCBpbXBvcnRhbnQsIGhvd2V2ZXIgcHJlZGljdG9ycyBhYm91dCBlZHVjYXRpb24gbGV2ZWxzIG9mIHRoZSBjb21tdW5pdGllcyB3aGVyZSB0aGUgbW9uaXRvciB3YXMgbG9jYXRlZCB3YXMgYW1vbmcgdGhlIHRvcCBtb3N0IGltcG9ydGFudC4gTm93IHdlIHNlZSB0aGF0IHBvcHVsYXRpb24gZGVuc2l0eSBhbmQgcHJveGltaXR5IHRvIHNvdXJjZXMgb2YgZW1pc3Npb25zIGFuZCByb2FkcyBhcmUgYW1vbmcgdGhlIHRvcCB0ZW4uDQoNCg0KTm93IGxldCdzIHRha2UgYSBsb29rIGF0IG1vZGVsIHBlcmZvcm1hbmNlIGJ5IGZpdHRpbmcgdGhlIGRhdGEgdXNpbmcgY3Jvc3MgdmFsaWRhdGlvbjoNCg0KIyMjIyB7LnJlY2FsbF9jb2RlX3F1ZXN0aW9uX2Jsb2NrfQ0KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+DQoNClNlZSBpZiB5b3UgY2FuIHJlY2FsbCBob3cgdG8gZG8gdGhpcy4NCg0KIyMjIw0KDQoqKioNCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5Pg0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFfQ0Kc2V0LnNlZWQoNDU2KQ0KcmVzYW1wbGVfUkZfZml0IDwtIHR1bmU6OmZpdF9yZXNhbXBsZXMoUkZfd2Zsb3csIHZmb2xkX3BtKQ0KY29sbGVjdF9tZXRyaWNzKHJlc2FtcGxlX1JGX2ZpdCkNCmBgYA0KDQo8L2RldGFpbHM+DQoqKioNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCnNldC5zZWVkKDQ1NikNCnJlc2FtcGxlX1JGX2ZpdCA8LSB0dW5lOjpmaXRfcmVzYW1wbGVzKFJGX3dmbG93LCB2Zm9sZF9wbSkNCmNvbGxlY3RfbWV0cmljcyhyZXNhbXBsZV9SRl9maXQpDQpgYGANCg0KTm93IGxldCdzIGNvbXBhcmUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoaXMgbW9kZWwgd2l0aCBvdXIgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWw6DQoNCmBgYHtyfQ0KIyBvdXIgaW5pdGlhbCBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbDoNCmNvbGxlY3RfbWV0cmljcyhyZXNhbXBsZV9maXQpDQpgYGANCg0KT0ssIHNvIG91ciBmaXJzdCBtb2RlbCBoYWQgYSBtZWFuIGBybXNlYCB2YWx1ZSBvZiAyLjE3Lg0KSXQgbG9va3MgbGlrZSB0aGUgcmFuZG9tIGZvcmVzdCBtb2RlbCBoYWQgIGEgbXVjaCBsb3dlciBgcm1zZWAgdmFsdWUgb2YgMS43Mi4NCg0KIyMjIyB7LnRoaW5rX3F1ZXN0aW9uX2Jsb2NrfQ0KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+DQoNCkRvIHlvdSByZWNhbGwgaG93IHRoZSBSTVNFIGlzIGNhbGN1bGF0ZWQ/DQoNCiMjIyMNCg0KKioqDQoNCjxkZXRhaWxzPiA8c3VtbWFyeT4gQ2xpY2sgaGVyZSB0byByZXZlYWwgdGhlIGFuc3dlci4gPC9zdW1tYXJ5Pg0KJCRSTVNFID0gXHNxcnR7XGZyYWN7XHN1bV97aT0xfV57bn17KFxoYXR7eV90fS0geV90KX1eMn17bn19JCQNCjwvZGV0YWlscz4gDQoNCklmIHdlIHR1bmVkIG91ciByYW5kb20gZm9yZXN0IG1vZGVsIGJhc2VkIG9uIHRoZSBudW1iZXIgb2YgdHJlZXMgb3IgdGhlIHZhbHVlIGZvciBgbXRyeWAgKHdoaWNoIGlzICJUaGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscyIpLCB3ZSBtaWdodCBnZXQgYSBtb2RlbCB3aXRoIGV2ZW4gYmV0dGVyIHBlcmZvcm1hbmNlLg0KDQpIb3dldmVyLCBvdXIgY3Jvc3MgdmFsaWRhdGVkIG1lYW4gcm1zZSB2YWx1ZSBvZiAxLjcyIGlzIHF1aXRlIGdvb2QgYmVjYXVzZSBvdXIgcmFuZ2Ugb2YgdHJ1ZSBvdXRjb21lIHZhbHVlcyBpcyBtdWNoIGxhcmdlcjogKGByIHJvdW5kKHJhbmdlKHRlc3RfcG0kdmFsdWUpLDMpYCkuDQoNCg0KIyMgKipNb2RlbCB0dW5pbmcqKg0KKioqDQoNCltIeXBlcnBhcmFtZXRlcnNdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS1iZXR3ZWVuLWEtcGFyYW1ldGVyLWFuZC1hLWh5cGVycGFyYW1ldGVyLykgYXJlIG9mdGVuIHRoaW5ncyB0aGF0IHdlIG5lZWQgdG8gc3BlY2lmeSBhYm91dCBhIG1vZGVsLiBGb3IgZXhhbXBsZSwgdGhlIG51bWJlciBvZiBwcmVkaWN0b3IgdmFyaWFibGVzIChvciBmZWF0dXJlcykgdGhhdCB3aWxsIGJlIHJhbmRvbWx5IHNhbXBsZWQgYXQgZWFjaCBzcGxpdCB3aGVuIGNyZWF0aW5nIHRoZSB0cmVlIG1vZGVscyBjYWxsZWQgYG10cnlgIGlzIGEgaHlwZXJwYXJhbWV0ZXIuIFRoZSBkZWZhdWx0IG51bWJlciBmb3IgcmVncmVzc2lvbiBhbmFseXNlcyBpcyB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgZGl2aWRlZCBieSAzLiBJbnN0ZWFkIG9mIGFyYml0cmFyaWx5IHNwZWNpZnlpbmcgdGhpcywgd2UgY2FuIHRyeSB0byBkZXRlcm1pbmUgdGhlIGJlc3Qgb3B0aW9uIGZvciBtb2RlbCBwZXJmb3JtYW5jZSBieSBhIHByb2Nlc3MgY2FsbGVkIHR1bmluZy4gDQoNCg0KTm93IGxldCdzIHRyeSBzb21lIHR1bmluZy4NCg0KTGV0J3MgdGFrZSBhIGNsb3NlciBsb29rIGF0IHRoZSBgbXRyeWAgYW5kIGBtaW5fbmAgaHlwZXJwYXJhbWV0cnMgaW4gb3VyIFJhbmRvbSBGb3Jlc3QgbW9kZWwuDQoNCldlIGFyZW4ndCBleGFjdGx5IHN1cmUgd2hhdCB2YWx1ZXMgb2YgYG10cnlgIGFuZCBgbWluX25gIGFjaGlldmUgZ29vZCBhY2N1cmFjeSB5ZXQga2VlcCBvdXIgbW9kZWwgZ2VuZXJhbGl6YWJsZSBmb3Igb3RoZXIgZGF0YS4NCg0KVGhpcyBpcyB3aGVuIG91ciBjcm9zcyB2YWxpZGF0aW9uIG1ldGhvZHMgYmVjb21lIHJlYWxseSBoYW5keSBiZWNhdXNlIG5vdyB3ZSBjYW4gdGVzdCBvdXQgZGlmZmVyZW50IHZhbHVlcyBmb3IgZWFjaCBvZiB0aGVzZSBoeXBlcnBhcmFtZXRlcnMgdG8gYXNzZXNzIHdoYXQgdmFsdWVzIHNlZW0gdG8gd29yayBiZXN0IGZvciBtb2RlbCBwZXJmb3JtYW5jZSBvbiB0aGVzZSByZXNhbXBsZXMgb2Ygb3VyIHRyYWluaW5nIHNldCBkYXRhLg0KDQpQcmV2aW91c2x5IHdlIHNwZWNpZmllZCBvdXIgbW9kZWwgbGlrZSBzbzoNCmBgYHtyfQ0KUkZfUE1fbW9kZWwgPC0gDQogIHBhcnNuaXA6OnJhbmRfZm9yZXN0KG10cnkgPSAxMCwgbWluX24gPSAzKSAlPiUNCiAgc2V0X2VuZ2luZSgicmFuZG9tRm9yZXN0IikgJT4lDQogIHNldF9tb2RlKCJyZWdyZXNzaW9uIikNCg0KUkZfUE1fbW9kZWwNCmBgYA0KTm93IGluc3RlYWQgb2Ygc3BlY2lmeWluZyBhIHZhbHVlIGZvciB0aGUgYG10cnlgIGFuZCBgbWluX25gIGFyZ3VtZW50cywgd2UgY2FuIHVzZSB0aGUgYHR1bmUoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIGxpa2Ugc286IGBtdHJ5ID0gdHVuZSgpYC4gVGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGVzZSBoeXBlcnBhcmFtZXRlcnMgYXJlIHRvIGJlIHR1bmVkLiANCg0KYGBge3J9DQoNCnR1bmVfUkZfbW9kZWwgPC0gcmFuZF9mb3Jlc3QobXRyeSA9IHR1bmUoKSwgbWluX24gPSB0dW5lKCkpICU+JQ0KICBzZXRfZW5naW5lKCJyYW5kb21Gb3Jlc3QiKSAlPiUNCiAgc2V0X21vZGUoInJlZ3Jlc3Npb24iKQ0KICAgIA0KDQp0dW5lX1JGX21vZGVsDQoNCmBgYA0KDQoNCkFnYWluIHdlIHdpbGwgYWRkIHRoaXMgdG8gYSB3b3JrZmxvdywgdGhlIG9ubHkgZGlmZmVyZW5jZSBoZXJlIGlzIHRoYXQgd2UgYXJlIHVzaW5nIGEgZGlmZmVyZW50IG1vZGVsIHNwZWNpZmljYXRpb24gd2l0aCBgdHVuZV9SRl9tb2RlbGAgaW5zdGVhZCBvZiBgUkZfbW9kZWxgOg0KDQpgYGB7cn0NCg0KUkZfdHVuZV93ZmxvdyA8LSB3b3JrZmxvd3M6OndvcmtmbG93KCkgJT4lDQogICAgICAgICAgICB3b3JrZmxvd3M6OmFkZF9yZWNpcGUoUkZfcmVjKSAlPiUNCiAgICAgICAgICAgIHdvcmtmbG93czo6YWRkX21vZGVsKHR1bmVfUkZfbW9kZWwpDQpSRl90dW5lX3dmbG93DQoNCmBgYA0KDQoNCk5vdyB3ZSBjYW4gdXNlIHRoZSBgdHVuZV9ncmlkKClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZSB0byBldmFsdWF0ZSBkaWZmZXJlbnQgY29tYmluYXRpb25zIG9mIHZhbHVlcyBmb3IgYG10cnlgIGFuZCBgbWluX25gIHVzaW5nIG91ciBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgb2Ygb3VyIHRyYWluaW5nIHNldCAoYHZmb2xkX3BtYCkgdG8gc2VlIHdoYXQgY29tYmluYXRpb24gb2YgdmFsdWVzIHBlcmZvcm1zIGJlc3QuDQoNClRvIHVzZSB0aGlzIGZ1bmN0aW9uIHdlIHdpbGwgc3BlY2lmeSB0aGUgd29ya2Zsb3cgdXNpbmcgdGhlIGBvYmplY3RgIGFyZ3VtZW50ICBhbmQgdGhlIHNhbXBsZXMgdG8gdXNlIHVzaW5nIHRoZSBgcmVzYW1wbGVzYCBhcmd1bWVudC4gVGhlIGBncmlkYCBhcmd1bWVudCBzcGVjaWZpZXMgaG93IG1hbnkgcG9zc2libGUgb3B0aW9ucyBmb3IgZWFjaCBhcmd1bWVudCBzaG91bGQgYmUgYXR0ZW1wdGVkLg0KDQpCeSBkZWZhdWx0IDEwIGRpZmZlcmVudCB2YWx1ZXMgd2lsbCBiZSBhdHRlbXB0ZWQgZm9yIGVhY2ggaHlwZXJwYXJhbWV0ZXIgdGhhdCBpcyBiZWluZyB0dW5lZC4NCg0KV2UgY2FuIHVzZSB0aGUgYGRvUGFyYWxsZWxgIHBhY2thZ2UgdG8gYWxsb3cgdXMgdG8gZml0IGFsbCB0aGVzZSBtb2RlbHMgdG8gb3VyIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBmYXN0ZXIuIFNvIGlmIHlvdSB3ZXJlIHBlcmZvcm1pbmcgdGhpcyBvbiBhIGNvbXB1dGVyIHdpdGggbXVsdGlwbGUgY29yZXMgb3IgcHJvY2Vzc29ycywgdGhlbiBkaWZmZXJlbnQgbW9kZWxzIHdpdGggZGlmZmVyZW50IGh5cGVycGFyYW1ldGVyIHZhbHVlcyBjYW4gYmUgZml0IHRvIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNhbXBsZXMgc2ltdWx0YW5lb3VzbHkgYWNyb3NzIGRpZmZlcmVudCBjb3JlcyBvciBwcm9jZXNzb3JzLiANCg0KWW91IGNhbiBzZWUgaG93IG1hbnkgY29yZXMgeW91IGhhdmUgYWNjZXNzIHRvIG9uIHlvdXIgc3lzdGVtIHVzaW5nIHRoZSBgZGV0ZWN0Q29yZXMoKWAgZnVuY3Rpb24gaW4gdGhlIGBwYXJhbGxlbGAgcGFja2FnZS4gDQoNCmBgYHtyfQ0KcGFyYWxsZWw6OmRldGVjdENvcmVzKCkNCmBgYA0KDQpUaGUgYHJlZ2lzdGVyRG9QYXJhbGxlbCgpYCBmdW5jdGlvbiB3aWxsIHVzZSB0aGUgbnVtYmVyIGZvciBjb3JlcyBzcGVjaWZpZWQgdXNpbmcgdGhlIGBjb3Jlcz1gIGFyZ3VlbWVudCwgb3IgaXQgd2lsbCBhc3NpZ24gaXQgYXV0b21hdGljYWxseSB0byBvbmUtaGFsZiBvZiB0aGUgbnVtYmVyIG9mIGNvcmVzIGRldGVjdGVkIGJ5IHRoZSBgcGFyYWxsZWxgIHBhY2thZ2UuIA0KDQpXZSBuZWVkIHRvIHVzZSBgc2V0LnNlZWQoKWAgaGVyZSBiZWNhdXNlIHRoZSB2YWx1ZXMgY2hvc2VuIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgbWF5IHZhcnkgaWYgd2UgcHJlZm9ybSB0aGlzIGV2YWx1YXRpb24gYWdhaW4gYmVjYXVzZSB0aGV5IGFyZSBjaG9zZW4gc2VtaS1yYW5kb21seSAobWVhbmluZyB0aGF0IHRoZXkgYXJlIHdpdGhpbiBhIHJhbmdlIG9mIHJlYXNvbmFibGUgdmFsdWVzIGJ1dCBzdGlsbCByYW5kb20pLg0KDQpOb3RlOiB0aGlzIHN0ZXAgd2lsbCB0YWtlIHNvbWUgdGltZS4NCg0KYGBge3J9DQpkb1BhcmFsbGVsOjpyZWdpc3RlckRvUGFyYWxsZWwoY29yZXM9MikNCnNldC5zZWVkKDEyMykNCnR1bmVfUkZfcmVzdWx0cyA8LSB0dW5lX2dyaWQob2JqZWN0ID0gUkZfdHVuZV93ZmxvdywgcmVzYW1wbGVzID0gdmZvbGRfcG0sIGdyaWQgPSAyMCkNCnR1bmVfUkZfcmVzdWx0cw0KYGBgDQoNCg0KU2VlIFt0aGUgdHVuZSBnZXR0aW5nIHN0YXJ0ZWQgZ3VpZGUgXShodHRwczovL3RpZHltb2RlbHMuZ2l0aHViLmlvL3R1bmUvYXJ0aWNsZXMvZ2V0dGluZ19zdGFydGVkLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgaW1wbGVtZW50aW5nIHRoaXMgaW4gYHRpZHltb2RlbHNgLg0KDQpJZiB5b3Ugd2FudGVkIG1vcmUgY29udHJvbCBvdmVyIHRoaXMgcHJvY2VzcyB5b3UgY291bGQgc3BlY2lmeSBob3cgdGhlIGRpZmZlcmVudCBwb3NzaWJsZSBvcHRpb25zIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgaW4gdGhlIGB0dW5lX2dyaWQoKWAgZnVuY3Rpb24gdXNpbmcgdGhlIGBncmlkXyooKWAgZnVuY3Rpb25zIG9mIHRoZSBgZGlhbHNgIHBhY2thZ2UgdG8gY3JlYXRlIGEgbW9yZSBzcGVjaWZpYyBncmlkLg0KDQpCZSBkZWZhdWx0IHRoZSB2YWx1ZXMgZm9yIHRoZSBoeXBlcnBhcmFtZXRlcnMgYmVpbmcgdHVuZWQgYXJlIGNob3NlbiBzZW1pLXJhbmRvbWx5IChtZWFuaW5nIHRoYXQgdGhleSBhcmUgd2l0aGluIGEgcmFuZ2Ugb2YgcmVhc29uYWJsZSB2YWx1ZXMgYnV0IHN0aWxsIHJhbmRvbSkuLg0KDQoNCk5vdyB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGFnYWluIHRvIHRha2UgYSBsb29rIGF0IHdoYXQgaGFwcGVuZWQgd2l0aCBvdXIgY3Jvc3MgdmFsaWRhdGlvbiB0ZXN0cy4gV2UgY2FuIHNlZSB0aGUgZGlmZmVyZW50IHZhbHVlcyBjaG9zZW4gZm9yIGBtdHJ5YCBhbmQgYG1pbl9uYCBhbmQgdGhlIG1lYW4gcm1zZSBhbmQgcnNxIHZhbHVlcyBhY3Jvc3MgdGhlIGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcy4NCg0KYGBge3J9DQp0dW5lX1JGX3Jlc3VsdHMlPiUNCiAgY29sbGVjdF9tZXRyaWNzKCkNCmBgYA0KDQpXZSBjYW4gbm93IHVzZSB0aGUgYHNob3dfYmVzdCgpYCBmdW5jdGlvbiBhcyBpdCB3YXMgdHJ1bHkgaW50ZW5kZWQsIHRvIHNlZSB3aGF0IHZhbHVlcyBmb3IgYG1pbl9uYCBhbmQgYG10cnlgIHJlc3VsdGVkIGluIHRoZSBiZXN0IHBlcmZvcm1hbmNlLg0KDQpgYGB7cn0NCnNob3dfYmVzdCh0dW5lX1JGX3Jlc3VsdHMsIG1ldHJpYyA9ICJybXNlIiwgbiA9MSkNCmBgYA0KVGhlcmUgd2UgaGF2ZSBpdC4uLiBsb29rcyBsaWtlIGFuIGBtdHJ5YCBvZiAxNyBhbmQgYG1pbl9uYCBvZiA0IGhhZCB0aGUgYmVzdCBgcm1zZWAgdmFsdWUuIFlvdSBjYW4gdmVyaWZ5IHRoaXMgaW4gdGhlIGFib3ZlIG91dHB1dCwgYnV0IGl0IGlzIGVhc2llciB0byBqdXN0IHB1bGwgdGhpcyByb3cgb3V0IHVzaW5nIHRoaXMgZnVuY3Rpb24uIFdlIGNhbiBzZWUgdGhhdCB0aGUgbWVhbiBgcm1zZWAgdmFsdWUgYWNyb3NzIHRoZSBjcm9zcyB2YWxpZGF0aW9uIHNldHMgd2FzIDEuNzEyLiBCZWZvcmUgdHVuaW5nIGl0IHdhcyAxLjcyNSAgd2l0aCBhIHNpbWlsYXIgYHN0ZF9lcnJgIHNvIHRoZSBwZXJmb3JtYW5jZSB3YXMgdmVyeSBzbGlnaHRseSBpbXByb3ZlZC4NCg0KDQojIyAqKkZpbmFsIG1vZGVsIHBlcmZvcm1hbmNlIGV2YWx1YXRpb24qKg0KKioqDQoNCk5vdyB0aGF0IHdlIGhhdmUgZGVjaWRlZCB0aGF0IHdlIGhhdmUgcmVhc29uYWJsZSBwZXJmb3JtYW5jZSB3aXRoIG91ciB0cmFpbmluZyBkYXRhLCB3ZSBjYW4gc3RvcCBidWlsZGluZyBvdXIgbW9kZWwgYW5kIGV2YWx1YXRlIHBlcmZvcm1hbmNlIHdpdGggb3VyIHRlc3RpbmcgZGF0YS4gDQoNCkhlcmUsIHdlIHdpbGwgdXNlIHRoZSByYW5kb20gZm9yZXN0IG1vZGVsIHRoYXQgd2UgYnVpbHQgdG8gcHJlZGljdCB2YWx1ZXMgZm9yIHRoZSBtb25pdG9ycyBpbiB0aGUgdGVzdGluZyBkYXRhIGFuZCB3ZSB3aWxsIHVzZSB0aGUgdmFsdWVzIGZvciBgbXRyeWAgYW5kIGBtaW5fbmAgdGhhdCB3ZSBqdXN0IGRldGVybWluZWQgYmFzZWQgb24gb3VyIHR1bmluZyBhbmFseXNpcyB0byBhY2hpZXZlIHRoZSBiZXN0IHBlcmZvcm1hbmNlLg0KDQpTbywgZmlyc3Qgd2UgbmVlZCB0byBzcGVjaWZ5IHRoZXNlIHZhbHVlcyBpbiBhIHdvcmtmbG93LiBXZSBjYW4gdXNlIHRoZSBgc2VsZWN0X2Jlc3QoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGdyYWIgdGhlIHZhbHVlcyB0aGF0IHdlcmUgZGV0ZXJtaW5lZCB0byBiZSBiZXN0IGZvciBgbXRyeWAgYW5kIGBtaW5fbmAuDQoNCg0KDQpgYGB7cn0NCg0KdHVuZWRfUkZfdmFsdWVzPC0gc2VsZWN0X2Jlc3QodHVuZV9SRl9yZXN1bHRzLCAicm1zZSIpDQp0dW5lZF9SRl92YWx1ZXMNCmBgYA0KDQpOb3cgd2UgY2FuIGZpbmFsaXplIHRoZSBtb2RlbC93b3JrZmxvdyB0aGF0IHdlIHdlIHVzZWQgZm9yIHR1bmluZyB3aXRoIHRoZXNlIHZhbHVlcy4NCg0KDQpgYGB7cn0NClJGX3R1bmVkX3dmbG93IDwtUkZfdHVuZV93ZmxvdyAlPiUNCiAgdHVuZTo6ZmluYWxpemVfd29ya2Zsb3codHVuZWRfUkZfdmFsdWVzKQ0KYGBgDQoNCg0KV2l0aCB0aGUgYHdvcmtmbG93c2AgcGFja2FnZSwgd2UgY2FuIHVzZSB0aGUgc3BsaXR0aW5nIGluZm9ybWF0aW9uIGZvciBvdXIgb3JpZ2luYWwgZGF0YSBgcG1fc3BsaXRgIHRvIGZpdCB0aGUgZmluYWwgbW9kZWwgb24gdGhlIGZ1bGwgdHJhaW5pbmcgc2V0IGFuZCBhbHNvIG9uIHRoZSB0ZXN0aW5nIGRhdGEgdXNpbmcgdGhlIGBsYXN0X2ZpdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHR1bmVgIHBhY2thZ2UuIE5vIHByZS1wcm9jZXNzaW5nIHN0ZXBzIGFyZSByZXF1aXJlZC4NCg0KVGhlIHJlc3VsdHMgd2lsbCBzaG93IHRoZSBwZXJmb3JtYW5jZSB1c2luZyB0aGUgdGVzdGluZyBkYXRhLg0KDQoNCmBgYHtyfQ0Kb3ZlcmFsbGZpdCA8LXR1bmU6Omxhc3RfZml0KFJGX3R1bmVkX3dmbG93LCBwbV9zcGxpdCkNCiAjIG9yDQpvdmVyYWxsZml0IDwtUkZfd2Zsb3cgJT4lDQogIHR1bmU6Omxhc3RfZml0KHBtX3NwbGl0KQ0KYGBgDQoNClRoZSBgb3ZlcmFsbGZpdGAgb3V0cHV0IGhhcyBhIGxvdCBvZiByZWFsbHkgdXNlZnVsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBtb2RlbCwgdGhlIHRlc3RpbmcgYW5kIHRyYWluaW5nIGRhdGEgc3BsaXQsIGFuZCB0aGUgcHJlZGljdGlvbnMgZm9yIHRoZSB0ZXN0aW5nIGRhdGEuDQoNClRvIHNlZSB0aGUgcGVyZm9ybWFuY2Ugb24gdGhlIHRlc3QgZGF0YSB3ZSBjYW4gdXNlIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIGxpa2Ugd2UgZGlkIGJlZm9yZS4NCmBgYHtyfQ0KICBjb2xsZWN0X21ldHJpY3Mob3ZlcmFsbGZpdCkNCiANCmBgYA0KDQpBd2Vzb21lISBXZSBjYW4gc2VlIHRoYXQgb3VyIHJtc2Ugb2YgMS40NCBpcyBxdWl0ZSBzaW1pbGFyIHdpdGggb3VyIHRlc3RpbmcgZGF0YSBjcm9zcyB2YWxpZGF0aW9uIHNldHMuIFdlIGFjaGlldmVkIHF1aXRlIGdvb2QgcGVyZm9ybWFuY2UsIHdoaWNoIHN1Z2dlc3RzIHRoYXQgd2Ugd291bGQgY291bGQgcHJlZGljdCBvdGhlciBsb2NhdGlvbnMgd2l0aCBtb3JlIHNwYXJzZSBtb25pdG9yaW5nIGJhc2VkIG9uIG91ciBwcmVkaWN0b3JzIHdpdGggcmVhc29uYWJsZSBhY2N1cmFjeS4NCg0KTm93IGlmIHlvdSB3YW50ZWQgdG8gdGFrZSBhIGxvb2sgYXQgdGhlIHByZWRpY3RlZCB2YWx1ZXMgZm9yIHRoZSB0ZXN0IHNldCAodGhlIDI5MiByb3dzIHdpdGggcHJlZGljdGlvbnMgb3V0IG9mIHRoZSA4NzYgb3JpZ2luYWwgbW9uaXRvciB2YWx1ZXMpIHlvdSBjYW4gdXNlIHRoZSAgYGNvbGxlY3RfcHJlZGljdGlvbnMoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lKClgIHBhY2thZ2U6DQoNCmBgYHtyfQ0KdGVzdF9wcmVkaWN0aW9ucyA8LWNvbGxlY3RfcHJlZGljdGlvbnMob3ZlcmFsbGZpdCkNCmBgYA0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFfQ0KdGVzdF9wcmVkaWN0aW9ucw0KYGBgDQoNCiMjIyMgey5zY3JvbGxhYmxlIH0NCmBgYHtyLCBlY2hvID1GQUxTRX0NCnRlc3RfcHJlZGljdGlvbnMgJT4lDQogIHByaW50KG4gPSAxZTMpDQpgYGANCg0KIyMjIw0KDQpOaWNlIQ0KDQojICoqRGF0YSBWaXN1YWxpemF0aW9uKioNCioqKg0KDQpPdXIgbWFpbiBxdWVzdGlvbiBmb3IgdGhpcyBjYXNlIHN0dWR5IHdhczogIA0KDQo+IENhbiB3ZSBwcmVkaWN0IGFubnVhbCBhdmVyYWdlIGFpciBwb2xsdXRpb24gY29uY2VudHJhdGlvbnMgYXQgdGhlIGdyYW51bGFyaXR5IG9mIHppcCBjb2RlIHJlZ2lvbmFsIGxldmVscyB1c2luZyBwcmVkaWN0b3JzIHN1Y2ggYXMgZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHksIHVyYmFuaXphdGlvbiwgcm9hZCBkZW5zaXR5LCBhcyB3ZWxsIGFzLCBzYXRlbGxpdGUgcG9sbHV0aW9uIGRhdGEgYW5kIGNoZW1pY2FsIG1vZGVsaW5nIGRhdGE/DQoNClRodXMgZmFyLCB3ZSBoYXZlIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyAoTUwpIG1vZGVsIHRvIHByZWRpY3QgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgYWlyIHBvbGx1dGlvbiBsZXZlbHMgYmFzZWQgb24gb3VyIHByZWRpY3RvciB2YXJpYWJsZXMgKG9yIGZlYXR1cmVzKS4NCg0KTm93LCBsZXQncyBtYWtlIGEgcGxvdCBvZiBvdXIgcHJlZGljdGVkIG91dGNvbWUgdmFsdWVzICgkXGhhdHtZfSQpIGFuZCBhY3R1YWwgb3V0Y29tZSB2YWx1ZXMgJFkkIHdlIG9ic2VydmVkLiANCg0KRmlyc3QsIGxldCdzIHN0YXJ0IGJ5IG1ha2luZyBhIHBsb3Qgb2Ygb3VyIG1vbml0b3JzLiANClRvIGRvIHRoaXMsIHdlIHdpbGwgdXNlIHRoZSBmb2xsb3dpbmcgcGFja2FnZXMgdG8gY3JlYXRlIGEgbWFwIG9mIHRoZSBVUzoNCg0KMS4gYHNmYCAtIHRoZSBzaW1wbGUgZmVhdHVyZXMgcGFja2FnZSBoZWxwcyB0byBjb252ZXJ0IGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcyBpbnRvIGBnZW9tZXRyeWAgdmFyaWFibGVzIHdoaWNoIGFyZSB1c2VmdWwgZm9yIG1ha2luZyAyRCBwbG90cw0KMi4gYG1hcHNgIC0gdGhpcyBwYWNrYWdlIGNvbnRhaW5zIGdlb2dyYXBoaWNhbCBvdXRsaW5lcyBhbmQgcGxvdHRpbmcgZnVuY3Rpb25zIHRvIGNyZWF0ZSBwbG90cyB3aXRoIG1hcHMgDQozLiBgcm5hdHVyYWxlYXJ0aGAtIHRoaXMgYWxsb3dzIGZvciBlYXN5IGludGVyYWN0aW9uIHdpdGggbWFwIGRhdGEgZnJvbSBbTmF0dXJhbCBFYXJ0aF0oaHR0cDovL3d3dy5uYXR1cmFsZWFydGhkYXRhLmNvbS8pIHdoaWNoIGlzIGEgcHVibGljIGRvbWFpbiBtYXAgZGF0YXNldA0KNC4gYHJnZW9zYCAtIHRoaXMgcGFja2FnZSBpbnRlcmZhY2VzIHdpdGggdGhlIEdlb21ldHJ5IEVuZ2luZS1PcGVuIFNvdXJjZSAoYEdFT1NgKSB3aGljaCBpcyBhbHNvIGhlbHBmdWwgZm9yIGNvb3JkaW5hdGUgY29udmVyc2lvbg0KDQpXZSB3aWxsIHN0YXJ0IHdpdGggZ2V0dGluZyBhbiBvdXRsaW5lIG9mIHRoZSBVUyB3aXRoIHRoZSBgbmVfY291bnRyaWVzKClgIGZ1bmN0aW9uIG9mIHRoZSBgcm5hdHVyYWxlYXJ0aGAgcGFja2FnZSB3aGljaCB3aWxsIHJldHVybiBwb2x5Z29ucyBvZiB0aGUgY291bnRyaWVzIGluIHRoZSBbTmF0dXJhbCBFYXJ0aF0oaHR0cDovL3d3dy5uYXR1cmFsZWFydGhkYXRhLmNvbS8pIGRhdGFzZXQuDQoNCmBgYHtyfQ0KDQp3b3JsZCA8LSBuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQ0KZ2xpbXBzZSh3b3JsZCkNCg0KYGBgDQoNCg0KSGVyZSB5b3UgY2FuIHNlZSB0aGUgZGF0YSBhYm91dCB0aGUgY291bnRyaWVzIGluIHRoZSB3b3JsZC4gTm90aWNlIHRoZSBgZ2VvbWV0cnlgIHZhcmlhYmxlLiBUaGlzIGlzIHVzZWQgdG8gY3JlYXRlIHRoZSBvdXRsaW5lcyB0aGF0IHdlIHdhbnQuIA0KDQpOb3cgd2UgY2FuIHVzZSB0aGUgYGdlb21fc2YoKWAgZnVuY3Rpb24gb2YgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlIHRvIGNyZWF0ZSBhIHZpc3VhbCBvZiBzaW1wbGUgZmVhdHVyZSAodGhlIGdlb21ldHJ5IGNvb3JkaW5hdGVzIGZvdW5kIGluIHRoZSBgZ2VvbWV0cnlgIHZhcmlhYmxlKS4NCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IHdvcmxkKSArDQogICAgZ2VvbV9zZigpIA0KDQpgYGANCg0KU28gbm93IHdlIGNhbiBzZWUgdGhhdCB3ZSBoYXZlIG91dGxpbmVzIG9mIGFsbCB0aGUgY291bnRyaWVzIGluIHRoZSB3b3JsZC4NCg0KV2Ugd2FudCB0byBsaW1pdCB0aGlzIGp1c3QgdG8gdGhlIGNvb3JkaW5hdGVzIGZvciB0aGUgVVMuIFdlIHdpbGwgZG8gdGhpcyBiYXNlZCBvbiB0aGUgY29vcmRpbmF0ZXMgd2UgZm91bmQgb24gV2lraXBlZGlhLiBBY2NvcmRpbmcgdG8gdGhpcyBbbGlua10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9leHRyZW1lX3BvaW50c19vZl90aGVfVW5pdGVkX1N0YXRlcyNXZXN0ZXJubW9zdCl7dGFyZ2V0PSJfYmxhbmsifSwgdGhlc2UgYXJlIHRoZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGJvdW5kcyBvZiB0aGUgY29udGluZW50YWwgVVM6DQoNCi0gdG9wID0gNDkuMzQ1Nzg2OCAjIG5vcnRoIGxhdA0KLSBsZWZ0ID0gLTEyNC43ODQ0MDc5ICMgd2VzdCBsb25nDQotIHJpZ2h0ID0gLTY2Ljk1MTM4MTIgIyBlYXN0IGxvbmcNCi0gYm90dG9tID0gIDI0Ljc0MzMxOTUgIyBzb3V0aCBsYXQNCg0KYGBge3J9DQoNCmdncGxvdChkYXRhID0gd29ybGQpICsNCiAgICBnZW9tX3NmKCkgKw0KICAgIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgDQogICAgICAgICAgICAgZXhwYW5kID0gRkFMU0UpDQpgYGANCk5vdyB3ZSBqdXN0IGhhdmUgYSBwbG90IHRoYXQgaXMgbW9zdGx5IGxpbWl0ZWQgdG8gdGhlIG91dGxpbmUgb2YgdGhlIFVTLg0KDQpOb3cgd2Ugd2lsbCB1c2UgdGhlIGBnZW9tX3BvaW50KClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90YCBwYWNrYWdlIHRvIGFkZCBzY2F0dGVyIHBsb3Qgb24gdG9wIG9mIHRoZSBtYXAuIFdlIHdhbnQgdG8gc2hvdyB3aGVyZSB0aGUgbW9uaXRvcnMgYXJlIGxvY2F0ZWQgYmFzZWQgb24gdGhlIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgdmFsdWVzIGluIHRoZSBkYXRhLg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gd29ybGQpICsNCiAgICBnZW9tX3NmKCkgKw0KICAgIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgDQogICAgICAgICAgICAgZXhwYW5kID0gRkFMU0UpKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IHBtLCBhZXMoeCA9IGxvbiwgeSA9IGxhdCksIHNpemUgPSAyLCANCiAgICAgICAgICAgICAgIHNoYXBlID0gMjMsIGZpbGwgPSAiZGFya3JlZCIpDQoNCmBgYA0KTmljZSENCg0KTm93IGxldCdzIGFkZCBjb3VudHkgbGluZXMuDQoNCkNvdW50eSBncmFwaGljYWwgZGF0YSBpcyBhdmFpbGFibGUgZnJvbSB0aGUgYG1hcHNgIHBhY2thZ2UuIA0KVGhlIGBzZmAgcGFja2FnZSB3aGljaCBhZ2FpbiBpcyBzaG9ydCBmb3Igc2ltcGxlIGZlYXR1cmVzIGNyZWF0ZXMgYSBkYXRhIGZyYW1lIGFib3V0IHRoaXMgZ3JhcGhpY2FsIGRhdGEgc28gdGhhdCB3ZSBjYW4gd29yayB3aXRoIGl0Lg0KDQpgYGB7cn0NCmNvdW50aWVzIDwtIA0KICBzZjo6c3RfYXNfc2YobWFwczo6bWFwKCJjb3VudHkiLCBwbG90ID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBUUlVFKSkNCg0KY291bnRpZXMNCmBgYA0KDQpOb3cgd2Ugd2lsbCB1c2UgdGhpcyBkYXRhIHdpdGhpbiB0aGUgYGdlb21fc2YoKWAgZnVuY3Rpb24gdG8gYWRkIHRoaXMgdG8gb3VyIHBsb3QuICBXZSB3aWxsIGFsc28gYWRkIGEgdGl0bGUgdXNpbmcgdGhlIGBnZ3RpdGxlKClgIGZ1bmN0aW9uLCBhcyB3ZWxsIGFzIHJlbW92ZSBheGlzIHRpY2tzIGFuZCB0aXRsZXMgdXNpbmcgdGhlIGB0aGVtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UuDQoNCmBgYHtyfQ0KbW9uaXRvcnMgPC0gZ2dwbG90KGRhdGEgPSB3b3JsZCkgKw0KICAgIGdlb21fc2YoZGF0YSA9IGNvdW50aWVzLCBmaWxsID0gTkEsIGNvbG9yID0gZ3JheSguNSkpKw0KICAgICAgY29vcmRfc2YoeGxpbSA9IGMoLTEyNSwgLTY2KSwgeWxpbSA9IGMoMjQuNSwgNTApLCANCiAgICAgICAgICAgICBleHBhbmQgPSBGQUxTRSkgKw0KICAgIGdlb21fcG9pbnQoZGF0YSA9IHBtLCBhZXMoeCA9IGxvbiwgeSA9IGxhdCksIHNpemUgPSAyLCANCiAgICAgICAgICAgICAgIHNoYXBlID0gMjMsIGZpbGwgPSAiZGFya3JlZCIpICsNCiAgICBnZ3RpdGxlKCJNb25pdG9yIExvY2F0aW9ucyIpICsNCiAgICB0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcy55PWVsZW1lbnRfYmxhbmsoKSkNCg0KbW9uaXRvcnMNCmBgYA0KDQpHcmVhdCENCg0KTm93LCBsZXQncyBhZGQgYSBmaWxsIGF0IHRoZSBjb3VudHktbGV2ZWwgZm9yIHRoZSB0cnVlIG1vbml0b3IgdmFsdWVzIG9mIGFpciBwb2xsdXRpb24uDQoNCkZpcnN0LCB3ZSBuZWVkIHRvIGdldCB0aGUgY291bnR5IG1hcCBkYXRhIHRoYXQgd2UganVzdCBnb3QgYW5kIG91ciBhaXIgcG9sbHV0aW9uIGRhdGEgdG8gaGF2ZSBzaW1pbGFybHkgZm9ybWF0dGVkIGNvdW50eSBuYW1lcyBzbyB0aGF0IHdlIGNhbiBjb21iaW5lIHRoZSBkYXRhc2V0cyB0b2dldGhlci4NCg0KV2UgY2FuIHNlZSB0aGF0IGluIHRoZSBgY291bnR5YCBkYXRhIHRoZSBjb3VudGllcyBhcmUgbGlzdGVkIGFmdGVyIHRoZSBzdGF0ZSBuYW1lIGFuZCBhIGNvbW1hLiBJbiBhZGRpdGlvbiB0aGV5IGFyZSBhbGwgbG93ZXIgY2FzZS4NCg0KDQpgYGB7cn0NCmhlYWQoY291bnRpZXMpDQpgYGANCg0KSW4gY29udHJhc3QsIG91ciBhaXIgcG9sbHV0aW9uIGBwbWAgZGF0YSBzaG93cyBjb3VudGllcyBhcyB0aXRsZXMgd2l0aCB0aGUgZmlyc3QgbGV0dGVyIGFzIHVwcGVyIGNhc2UuIA0KDQpgYGB7cn0NCmRwbHlyOjpwdWxsKHBtLCBjb3VudHkpICU+JQ0KICBoZWFkKCkNCmBgYA0KDQpXZSBjYW4gdXNlIHRoZSBgc2VwYXJhdGUoKWAgZnVuY3Rpb24gb2YgdGhlIGB0aWR5cmAgcGFja2FnZSB0byBzZXBhcmF0ZSB0aGUgYElEYCB2YXJpYWJsZSBvZiBvdXIgYGNvdW50aWVzYCBkYXRhIGludG8gdHdvIGB2YXJpYWJsZXNgIGJhc2VkIG9uIHRoZSBjb21tYSBhcyBhIHNlcGFyYXRvci4NCg0KYGBge3J9DQpjb3VudGllcyAlPD4lIA0KICB0aWR5cjo6c2VwYXJhdGUoSUQsIGludG8gPSBjKCJzdGF0ZSIsICJjb3VudHkiKSwgc2VwID0gIiwiKQ0KDQpoZWFkKGNvdW50aWVzKQ0KYGBgDQpOb3cgd2UganVzdCBuZWVkIHRvIG1ha2UgdGhlc2UgbmFtZXMgaW4gdGhlIG5ldyBgY291bnR5YCB2YXJpYWJsZSBvZiB0aGUgYGNvdW50aWVzYCBkYXRhIHRvIGJlIGluIHRpdGxlIGZvcm1hdC4gV2UgY2FuIHVzZSB0aGUgYHN0cl90b190aXRsZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UgdG8gZG8gdGhpcy4gDQpgYGB7cn0NCmNvdW50aWVzW1siY291bnR5Il1dIDwtIHN0cmluZ3I6OnN0cl90b190aXRsZShjb3VudGllc1tbImNvdW50eSJdXSkNCmBgYA0KDQpHcmVhdCEgTm93IHRoZSBjb3VudHkgaW5mb3JtYXRpb24gaXMgdGhlIHNhbWUgZm9yIHRoZSBgY291bnRpZXNgIGFuZCBgcG1gIGRhdGEuDQoNCldlIGNhbiB1c2UgdGhlIGBpbm5lcl9qb2luKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gam9pbiB0aGUgZGF0YXNldHMgdG9nZXRoZXIgYmFzZWQgb24gdGhlIGBjb3VudHlgIHZhcmlhYmxlcyBpbiBlYWNoLiBUaGlzIGZ1bmN0aW9uIHdpbGwga2VlcCBhbGwgcm93cyB0aGF0IGFyZSBpbiBib3RoIGRhdGFzZXRzLg0KDQpgYGB7cn0NCm1hcF9kYXRhIDwtZHBseXI6OmlubmVyX2pvaW4oY291bnRpZXMsIHBtLCBieSA9ICJjb3VudHkiKQ0KDQpnbGltcHNlKG1hcF9kYXRhKQ0KDQpgYGANCk5pY2UhIHdlIGNhbiBzZWUgdGhhdCB3ZSBoYXZlIGFkZCBhIGBnZW9tYCB2YXJpYWJsZSB0byB0aGUgYHBtYCBkYXRhLg0KDQpOb3cgd2UgY2FuIHVzZSB0aGlzIHRvIGNvbG9yIHRoZSBjb3VudGllcyBpbiBvdXIgcGxvdCBiYXNlZCBvbiB0aGUgYHZhbHVlYCB2YXJpYWJsZSBvZiBvdXIgYHBtYCBkYXRhLCB3aGljaCB5b3UgbWF5IHJlY2FsbCBpcyB0aGUgYWN0dWFsIG1vbml0b3IgZGF0YSBmb3IgZmluZSBwYXJ0aWN1bGF0ZSBhaXIgcG9sbHV0aW9uIGF0IGVhY2ggbW9uaXRvci4gDQoNCldFIGNhbiBkbyBzbyB1c2luZyB0aGUgYHNjYWxlX2ZpbGxfZ3JhZGllbnRuKClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90MmAgcGFja2FnZSB3aGljaCBjcmVhdGVzIGNvbG9yIGdyYWRpZW50IGJhc2VkIG9uIGEgdmFyaWFibGUuIEluIHRoaXMgY2FzZSBpdCBpcyB0aGUgdmFyaWFibGUgdGhhdCB3YXMgc3BlY2lmaWVkIGFzIHRoZSBgZmlsbGAgaW4gdGhlIGBhZXNgIGZ1bmN0aW9uIG9mIHRoZSBgZ2VvbV9zZigpYCBmdW5jdGlvbi4gV2Ugc3BlY2lmaWVkIHRoYXQgaXQgd291bGQgYmUgdGhlIGB2YWx1ZWAgdmFyaWFibGUgb2YgdGhlIGBwbWAgZGF0YS4NCg0KVGhpcyBgc2NhbGVfZmlsbF9ncmFkaWVudG4oKWAgZnVuY3Rpb24gIGFsc28gYWxsb3dzIHlvdSB0byBzcGVjaWZ5IHRoZSBjb2xvcnMsIHdoYXQgdG8gZG8gYWJvdXQgTkEgdmFsdWVzIChzaG91bGQgdGhleSBiZSBhIHNwZWNpZmljIGNvbG9yIG9yIHRyYW5zcGFyZW50KSBhbmQgdGhlIGJyZWFrcywgbGltaXRzLCBsYWJlbHMgYW5kIG5hbWUvdGl0bGUgb24gdGhlIGxlZ2VuZCBmb3IgdGhlIGNvbG9yIGdyYWRpZW50LiANCg0KYGBge3J9DQoNCnRydXRoIDwtZ2dwbG90KGRhdGEgPSB3b3JsZCkgKw0KICBjb29yZF9zZih4bGltID0gYygtMTI1LCAtNjYpLCB5bGltID0gYygyNC41LCA1MCksIGV4cGFuZCA9IEZBTFNFKSsNCiAgICBnZW9tX3NmKGRhdGEgPSBtYXBfZGF0YSwgYWVzKGZpbGwgPSB2YWx1ZSkpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3Vycz10b3BvLmNvbG9ycyg3KSwgbmEudmFsdWUgPSAidHJhbnNwYXJlbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzPWMoMCwxMCwyMCksbGFiZWxzPWMoMCwxMCwyMCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHM9YygwLDIzLjUpLCBuYW1lID0gIlBNIHVnL20zIikgKw0KICBnZ3RpdGxlKCJUcnVlIFBNIDIuNSBsZXZlbHMiKSArDQogICAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpDQoNCnRydXRoDQoNCmBgYA0KTmljZSENCg0KTm93IGxldCdzIGRvIHRoZSBzYW1lIHdpdGggb3VyIHByZWRpY3RlZCBvdXRjb21lIHZhbHVlcy4NCg0KTGV0J3MgZ3JhYiBib3RoIHRoZSB0ZXN0aW5nIGFuZCB0cmFpbmluZyBwcmVkaWN0ZWQgb3V0Y29tZSB2YWx1ZXMgc28gdGhhdCB3ZSBoYXZlIGFzIG11Y2ggZGF0YSBhcyBwb3NzaWJsZS4gDQoNCkZpcnN0IHdlIG5lZWQgdG8gZml0IG91ciB0cmFpbmluZyBkYXRhIHdpdGggb3VyIGZpbmFsIG1vZGVsIHRvIGJlIGFibGUgdG8gZ2V0IHRoZSBwcmVkaWN0aW9ucyBmb3IgdGhlIG1vbml0b3JzIGluY2x1ZGVkIGluIHRoZSB0cmFpbmluZyBzZXQuIFdlIGRpZCB0aGlzIHVzaW5nIHRoZSBgbGFzdF9maXQoKWAgZnVuY3Rpb24sIGJ1dCB0aGUgb3V0cHV0IG9mIHRoaXMgbWFrZXMgaXQgZGlmZmljdWx0IHRvIGdyYWIgdGhlIHByZWRpY3RlZCB2YWx1ZXMgZm9yIHRoZSB0cmFpbmluZyBkYXRhLCBhbmQgaXQgaXMgYWxzbyBkaWZmaWN1bHQgdG8gZ2V0IHRoZSBpZCB2YXJpYWJsZXMgZm9yIHRoZSB0ZXN0aW5nIGRhdGEuIA0KDQoNClRodXMgd2Ugd2lsbCB1c2UgdGhlIHBhcnNuaXAgYGZpdCgpYCBhbmQgYHByZWRpY3QoKWAgZnVuY3Rpb25zIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZSB0byBkbyB0aGlzIGxpa2Ugc286DQoNCiMjIyMgey50aGlua19xdWVzdGlvbl9ibG9ja30NCjxiPjx1PiBRdWVzdGlvbiBPcHBvcnR1bml0eSA8L3U+PC9iPg0KDQpXaHkgZG8gd2Ugbm90IG5lZWQgcHJlLXByb2Nlc3NlZCBkYXRhPw0KDQojIyMjDQoNCioqKg0KDQo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gcmV2ZWFsIHRoZSBhbnN3ZXIuIDwvc3VtbWFyeT4NCg0KU2luY2Ugd2UgYXJlIHVzaW5nIGEgd29ya2Zsb3csIHRoZSBkYXRhIHdpbGwgYmUgcHJlLXByb2Nlc3NlZCB3aGVuIGl0IGlzIGZpdCBhcyB3ZWxsLg0KDQo8L2RldGFpbHM+DQoqKioNCg0KDQpgYGB7cn0NCg0KUkZfZmluYWxfdHJhaW5fZml0IDwtIHBhcnNuaXA6OmZpdChSRl90dW5lZF93ZmxvdywgZGF0YSA9IHRyYWluX3BtKQ0KUkZfZmluYWxfdGVzdF9maXQgPC0gcGFyc25pcDo6Zml0KFJGX3R1bmVkX3dmbG93LCBkYXRhID0gdGVzdF9wbSkNCg0KDQp2YWx1ZXNfcHJlZF90cmFpbiA8LSANCiAgcHJlZGljdChSRl9maW5hbF90cmFpbl9maXQsIHRyYWluX3BtKSAlPiUgDQogIGJpbmRfY29scyh0cmFpbl9wbSAlPiUgc2VsZWN0KHZhbHVlLCBmaXBzLCBjb3VudHksIGlkKSkgDQoNCnZhbHVlc19wcmVkX3RyYWluDQoNCnZhbHVlc19wcmVkX3Rlc3QgPC0gDQogIHByZWRpY3QoUkZfZmluYWxfdGVzdF9maXQsIHRlc3RfcG0pICU+JSANCiAgYmluZF9jb2xzKHRlc3RfcG0gJT4lIHNlbGVjdCh2YWx1ZSwgZmlwcywgY291bnR5LCBpZCkpIA0KDQp2YWx1ZXNfcHJlZF90ZXN0DQpgYGANCg0KTm93IHdlIGNhbiBjb21iaW5lIHRoaXMgZGF0YSBmb3IgdGhlIHByZWRpY3Rpb25zIGZvciBhbGwgbW9uaXRvcnMgdXNpbmcgdGhlIGBiaW5kX3Jvd3MoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSwgd2hpY2ggd2lsbCBlc3NlbnRpYWxseSBhcHBlbmQgdGhlIHNlY29uZCBkYXRhc2V0IHRvIHRoZSBmaXJzdC4NCg0KYGBge3J9DQphbGxfcHJlZCA8LSBiaW5kX3Jvd3ModmFsdWVzX3ByZWRfdGVzdCwgdmFsdWVzX3ByZWRfdHJhaW4pDQoNCmFsbF9wcmVkDQpgYGANCg0KR3JlYXQhIGFzIHdlIGNhbiBzZWUgdGhlcmUgYXJlIDg3NiB2YWx1ZXMgbGlrZSB3ZSB3b3VsZCBleHBlY3QgZm9yIGFsbCBvZiB0aGUgbW9uaXRvcnMuIFdlIGNhbiB1c2UgdGhlIGBjb3VudHlgIHZhcmlhYmxlIHRvIGNvbWJpbmUgdGhpcyB3aXRoIHRoZSBgY291bnRpZXNgIGRhdGEgbGlrZSB3ZSBkaWQgd2l0aCB0aGUgYHBtYCBkYXRhIHByZXZpb3VzbHkgc28gdGhhdCB3ZSBjYW4gdXNlIHRoZSBgdmFsdWVgIHZhcmlhYmxlIGFzIGEgY29sb3Igc2NoZW1lIGZvciBvdXIgbWFwLg0KDQoNCmBgYHtyfQ0KbWFwX2RhdGEgPC0gaW5uZXJfam9pbihjb3VudGllcywgYWxsX3ByZWQsIGJ5ID0gImNvdW50eSIpDQoNCnByZWQgPC0gZ2dwbG90KGRhdGEgPSB3b3JsZCkgKw0KICAgICAgICAgIGNvb3JkX3NmKHhsaW0gPSBjKC0xMjUsIC02NiksIHlsaW0gPSBjKDI0LjUsIDUwKSwgDQogICAgICAgICAgICAgICAgIGV4cGFuZCA9IEZBTFNFKSArDQogICAgZ2VvbV9zZihkYXRhID0gbWFwX2RhdGEsIGFlcyhmaWxsID0gLnByZWQpKSArDQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnM9dG9wby5jb2xvcnMoNyksIG5hLnZhbHVlID0gInRyYW5zcGFyZW50IiwNCiAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzPWMoMCwxMCwyMCksbGFiZWxzPWMoMCwxMCwyMCksDQogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsMjMuNSksIG5hbWUgPSAiUE0gdWcvbTMiKSArDQogIGdndGl0bGUoIlByZWRpY3RlZCBQTSAyLjUgbGV2ZWxzIikrDQogICAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGlja3MueT1lbGVtZW50X2JsYW5rKCkpDQoNCnByZWQNCmBgYA0KDQpOb3cgd2Ugd2lsbCB1c2UgdGhlIGBwYXRjaHdvcmtgIHBhY2thZ2UgdG8gY29tYmluZSBvdXIgbGFzdCB0d28gcGxvdHMuIFRoaXMgYWxsb3dzIHVzIHRvIGNvbWJpbmUgcGxvdHMgdXNpbmcgdGhlIGArYCBvciB0aGUgYC9gIC4gVGhlIGArYCB3aWxsIHBsYWNlIHBsb3RzIHNpZGUgYnkgc2lkZSBhbmQgdGhlIGAvYCB3aWxsIHBsYWNlIHBsb3RzIHRvcCB0byBib3R0b20uDQoNCg0KTm93IGxldCdzIGp1c3QgY29tYmluZSB0aGUgdHJ1dGggcGxvdCBhbmQgdGhlIHByZWRpY3Rpb24gcGxvdHMgdG9nZXRoZXI6DQpgYGB7cn0NCnRydXRoL3ByZWQNCg0KYGBgDQoNCldlIGNhbiBzZWUgdGhhdCB0aGUgcHJlZGljdGVkIGZpbmUgcGFydGljbGUgYWlyIHBvbGx1dGlvbiB2YWx1ZXMgaW4gKHVnL20zKSBhcmUgcXVpdGUgc2ltaWxhciB0byB0aGUgdHJ1ZSB2YWx1ZXMgbWVhc3VyZWQgYnkgdGhlIGFjdHVhbCBncmF2aW1ldHJpYyBtb25pdG9ycy4gV2UgY2FuIGFsc28gc2VlIHRoYXQgc291dGhlcm4gQ2FsaWZvcm5pYSBoYXMgc29tZSBsYXJnZSBjb3VudGllcyB3aXRoIHdvcnNlIHBvbGx1dGlvbiAoYXMgdGhleSBhcmUgeWVsbG93IGFuZCB0aHVzIGhhdmUgbXVjaCBoaWdoZXIgcGFydGljdWxhdGUgbWF0dGVyIGxldmVscykuDQoNCkxldCdzIGFkZCBzb21lIHRleHQgdG8gb3VyIHBsb3QgdG8gZXhwbGFpbiBpdCBhIGJpdCBtb3JlLiBXZSBjYW4gZG8gc28gdXNpbmcgdGhlIGBwbG90X2Fubm90YXRpb24oKWAgZnVuY3Rpb24gb2YgdGhlIGBwYXRjaHdvcmtgIHBhY2thZ2UuIFRoZSBgdGhlbWVgIGFyZ3VtZW50IG9mIHRoaXMgZnVuY3Rpb24gdGFrZXMgdGhlIHNhbWUgdGhlbWUgaW5mb3JtYXRpb24gdXNpbmcgdGhlIGB0aGVtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UgYXMgd2hlbiBjcmVhdGluZyBgZ2dwbG90MmBwbG90cy4NCg0KYGBge3J9DQoodHJ1dGgvcHJlZCkgKyBwbG90X2Fubm90YXRpb24odGl0bGUgPSAiTWFjaGluZSBMZWFybmluZyBNZXRob2RzIEFsbG93IGZvciBQcmVkaWN0aW9uIG9mIEFpciBQb2xsdXRpb24iLCBzdWJ0aXRsZSA9ICJBIHJhbmRvbSBmb3Jlc3QgbW9kZWwgcHJlZGljdHMgdHJ1ZSBtb25pdG9yZWQgbGV2ZWxzIG9mIGZpbmUgcGFydGljdWxhdGUgbWF0dGVyIChQTSAyLjUpIGFpciBwb2xsdXRpb24gYmFzZWQgb25cbmRhdGEgYWJvdXQgcG9wdWxhdGlvbiBkZW5zaXR5IGFuZCBvdGhlciBwcmVkaWN0b3JzIHJlYXNvbmFibHkgd2VsbCwgdGh1cyBzdWdnZXN0aW5nIHRoYXQgd2UgY2FuIHByZWRpY3QgbGV2ZWxzXG5vZiBwb2xsdXRpb24gaW4gcGxhY2VzIHdpdGggcG9vciBtb25pdG9yaW5nIiwgdGhlbWUgPSB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPTEyLCBmYWNlID0gImJvbGQiKSwgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpKQ0KDQpgYGANCg0KDQpgYGB7ciwgZWNobyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBldmFsPUZBTFNFLCBpbmNsdWRlID0gRkFMU0V9DQpwbmcoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5fcGxvdF9tYXBzLnBuZyIpLCANCiAgICBoZWlnaHQgPSAxNTAwLCB3aWR0aCA9IDIwMDAsIHJlcyA9IDMwMCkNCih0cnV0aC9wcmVkKSArIHBsb3RfYW5ub3RhdGlvbih0aXRsZSA9ICJNYWNoaW5lIExlYXJuaW5nIE1ldGhvZHMgQWxsb3cgZm9yIFByZWRpY3Rpb24gb2YgQWlyIFBvbGx1dGlvbiIsIHN1YnRpdGxlID0gIkEgcmFuZG9tIGZvcmVzdCBtb2RlbCBwcmVkaWN0cyB0cnVlIG1vbml0b3JlZCBsZXZlbHMgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgKFBNIDIuNSkgYWlyIHBvbGx1dGlvbiBiYXNlZCBvblxuZGF0YSBhYm91dCBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIG90aGVyIHByZWRpY3RvcnMgcmVhc29uYWJseSB3ZWxsLCB0aHVzIHN1Z2dlc3RpbmcgdGhhdCB3ZSBjYW4gcHJlZGljdCBsZXZlbHNcbm9mIHBvbGx1dGlvbiBpbiBwbGFjZXMgd2l0aCBwb29yIG1vbml0b3JpbmciLCB0aGVtZSA9IHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9MTIsIGZhY2UgPSAiYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkpDQpkZXYub2ZmKCkNCmBgYA0KDQojICoqU3VtbWFyeSoqDQoqKioNCg0KIyMgKipTeW5vcHNpcyoqDQoqKioNCg0KSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSBleHBsb3JlZCBncmF2aW1ldHJpYyBtb25pdG9yaW5nIGRhdGEgb2YgZmluZSBwYXJ0aWN1bGF0ZSBtYXR0ZXIgYWlyIHBvbGx1dGlvbiAob3V0Y29tZSB2YXJpYWJsZSkuIA0KT3VyIGdvYWwgd2FzIHRvIGFibGUgdG8gcHJlZGljdCBhaXIgcG9sbHV0aW9uIHdoZXJlIHdlIG9ubHkgaGFkIHByZWRpY3RvciB2YXJpYWJsZXMgKG9yIGZlYXR1cmVzKSB3aXRob3V0IGhhdmluZyBvYnNlcnZlZCBhIGNvcnJlc3BvbmRpbmcgbWVhc3VyZW1lbnQgb2YgYWlyIHBvbGx1dGlvbi4NCg0KT3VyIGxlYXJuaW5nIG9iamVjdGl2ZXMgd2VyZTogDQoNCi0gSW50cm9kdWNlIGNvbmNlcHRzIGluIG1hY2hpbmUgbGVhcm5pbmcNCi0gRGVtb25zdHJhdGUgaG93IHRvIGJ1aWxkIGEgbWFjaGluZSBsZWFybmluZyBtb2RlbCB3aXRoIGB0aWR5bW9kZWxzYA0KLSBEZW1vbnN0cmF0ZSBob3cgdG8gdmlzdWFsaXplIGdlby1zcGF0aWFsIGRhdGEgdXNpbmcgYGdncGxvdDJgDQoNClVzaW5nIHRoZSBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBidWlsdCBpbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIGNvdWxkIG5vdyBleHRlbmQgdGhpcyBtb2RlbCB0byBiZSB1c2VkIHRvIHByZWRpY3QgYWlyIHBvbGx1dGlvbiBsZXZlbHMgaW4gYXJlYXMgd2l0aCBwb29yIG1vbml0b3JpbmcsIHRvIGhlbHAgaWRlbnRpZnkgcmVnaW9ucyB3aGVyZSBwb3B1bGF0aW9ucyBtYXliZSBlc3BlY2lhbGx5IGF0IHJpc2sgZm9yIHRoZSBoZWFsdGggZWZmZWN0cyBvZiBhaXIgcG9sbHV0aW9uLiAgDQoNCkFuYWx5c2VzIGxpa2UgdGhlIG9uZSBpbiBvdXIgY2FzZSBzdHVkeSBhcmUgaW1wb3J0YW50IGZvciBkZWZpbmluZyB3aGljaCBncm91cHMgY291bGQgYmVuZWZpdCB0aGUgbW9zdCBmcm9tIGludGVydmVudGlvbnMsIGVkdWNhdGlvbiwgYW5kIHBvbGljeSBjaGFuZ2VzIHdoZW4gYXR0ZW1wdGluZyB0byBtaXRpZ2F0ZSBwdWJsaWMgaGVhbHRoIGNoYWxsZW5nZXMuIFlvdSBjYW4gc2VlIGluIHRoaXMgW2FydGljbGVdKGh0dHBzOi8vd3d3Lm5lam0ub3JnL2RvaS9mdWxsLzEwLjEwNTYvTkVKTW9hMTcwMjc0Nyl7dGFyZ2V0PSJfYmxhbmsifSB0aGF0IG1hbnkgYWRkaXRpb25hbCBjb25zaWRlcmF0aW9ucyB3b3VsZCBiZSBpbnZvbHZlZCB0byBhZGVxdWF0ZWx5IHVuZGVyc3RhbmQgdGhlIGRhdGEgZW5vdWdoIHRvIHJlY29tbWVuZCBwb2xpY3kgY2hhbmdlcy4NCg0KSGVyZSBhcmUgc29tZSB2aXN1YWwgc3VtbWFyaWVzIGFib3V0IHdoYXQgd2UgbGVhcm5lZCBhYm91dCB1c2luZyBgdGlkeW1vZGVsc2AgdG8gcGVyZm9ybSBwcmVkaWN0aW9uIGFuYWx5c2VzLg0KDQpGaXJzdCB0aGUgbWluaW1hbCBzdGVwcyByZXF1aXJlZDoNCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iODAwcHgifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwidGlkeW1vZGVsc0Jhc2ljcy5wbmciKSkNCmBgYA0KDQoNCkhlcmUgaXMgYSBndWlkZSBmb3IgbW9yZSBhZHZhbmNlZCBhbmFseXNlcyBpbnZvbHZpbmcgcHJlcHJvY2Vzc2luZywgY3Jvc3MgdmFsaWRhdGlvbiwgb3IgdHVuaW5nOg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJmdWxsX3RpZHltb2RlbHNfb3ZlcnZpZXcucG5nIikpDQpgYGANCg0KDQoNCg0KPGRldGFpbHM+PHN1bW1hcnk+IENsaWNrIGhlcmUgZm9yIG1vcmUgb24gd2hhdCB3ZSBsZWFybmVkIHdpdGggYHRpZHltb2RlbHNgIDwvc3VtbWFyeT4NCg0KSGVyZSwgd2UgcHJvdmlkZSBhbiBvdmVydmlldyBvZiB0aGUgYHRpZHltb2RlbHNgIGZyYW1ld29yay4gDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImVjb3N5c3RlbS5wbmciKSkNCmBgYA0KDQoNCldlIHBlcmZvcm1lZCB0aGUgbWFqb3Igc3RlcHMgb2YgbWFjaGluZSBsZWFybmluZyB0aGF0IHdlIGludHJvZHVjZWQgaW4gdGhlIGJlZ2lubmluZyBvZiB0aGUgZGF0YSBhbmFseXNpczogIA0KDQoxLiBEYXRhIGV4cGxvcmF0aW9uICANCg0KV2UgdXNlZCBwYWNrYWdlcyBsaWtlIGBza2ltcmAsIGBzdW1tYXJ5dG9vbHNgLCBgY29ycnBsb3RgLCBhbmQgYEdHYWxseWAgdG8gYmV0dGVyIHVuZGVyc3RhbmQgb3VyIGRhdGEuIFRoZXNlIHBhY2thZ2VzIGNhbiB0ZWxsIHVzIGhvdyBtYW55IG1pc3NpbmcgdmFsdWVzIGVhY2ggdmFyaWFibGUgaGFzIChpZiBhbnkpLCB0aGUgY2xhc3Mgb2YgZWFjaCB2YXJpYWJsZSwgdGhlIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgZm9yIGVhY2ggdmFyaWFibGUsIHRoZSBzcGFyc2l0eSBvZiBlYWNoIHZhcmlhYmxlLCBhbmQgdGhlIGxldmVsIG9mIGNvcnJlbGF0aW9uIGJldHdlZW4gdmFyaWFibGVzLiAgDQoNCjIuIERhdGEgc3BsaXR0aW5nIA0KDQpXZSB1c2VkIHRoZSBgcnNhbXBsZWAgcGFja2FnZSB0byBmaXJzdCBwZXJmb3JtIGFuIGluaXRpYWwgc3BsaXQgb2Ygb3VyIGRhdGEgaW50byB0d28gcGllY2VzOiBhIHRyYWluaW5nIHNldCBhbmQgYSB0ZXN0aW5nIHNldC4gVGhlIHRyYWluaW5nIHNldCB3YXMgdXNlZCB0byBvcHRpbWl6ZSB0aGUgbW9kZWwsIHdoaWxlIHRoZSB0ZXN0aW5nIHNldCB3YXMgdXNlZCBvbmx5IHRvIGV2YWx1YXRlIHRoZSBwZXJmb3JtYW5jZSBvZiBvdXIgZmluYWwgbW9kZWwuIFdlIGFsc28gdXNlZCB0aGUgYHJzYW1wbGVgIHBhY2thZ2UgdG8gY3JlYXRlIGNyb3NzIHZhbGlkYXRpb24gc3Vic2V0cyBvZiBvdXIgdHJhaW5pbmcgZGF0YS4gVGhpcyBhbGxvd2VkIHVzIHRvIGJldHRlciBhc3Nlc3MgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciB0ZXN0ZWQgbW9kZWxzIHVzaW5nIG91ciB0cmFpbmluZyBkYXRhLiAgDQoNCjMuIFZhcmlhYmxlIGFzc2lnbm1lbnQgYW5kIHByZS1wcm9jZXNzaW5nICAgDQoNCldlIHVzZWQgdGhlIGByZWNpcGVzYCBwYWNrYWdlIHRvIGFzc2lnbiB2YXJpYWJsZSByb2xlcyAoc3VjaCBhcyBvdXRjb21lLCBwcmVkaWN0b3IsIGFuZCBpZCB2YXJpYWJsZSkuIFdlIGFsc28gdXNlZCB0aGlzIHBhY2thZ2UgdG8gY3JlYXRlIGEgcmVjaXBlIGZvciBwcmUtcHJvY2Vzc2luZyBvdXIgdHJhaW5pbmcgYW5kIHRlc3RpbmcgZGF0YS4gVGhpcyBpbnZvbHZlZCBzdGVwcyBzdWNoIGFzOiBgIHN0ZXBfZHVtbXlgIHRvIGNyZWF0ZSBkdW1teSBudW1lcmljIGVuY29kaW5ncyBvZiBvdXIgY2F0ZWdvcmljYWwgdmFyaWFibGVzLCBgc3RlcF9jb3JyYCB0byByZW1vdmUgaGlnaGx5IGNvcnJlbGF0ZWQgdmFyaWFibGVzLCBgc3RlcF9uenZgIHRvIHJlbW92ZSBuZWFyIHplcm8gdmFyaWFuY2UgdmFyaWFibGVzIHRoYXQgd291bGQgY29udHJpYnV0ZSBsaXR0bGUgdG8gb3VyIG1vZGVsIGFuZCBwb3RlbnRpYWxseSBhZGQgbm9pc2UuICBXZSBsZWFybmVkIHRoYXQgb25jZSBvdXIgcmVjaXBlIHdhcyBjcmVhdGVkIGFuZCBwcmVwcGVkIHVzaW5nIGBwcmVwKClgd2UgY291bGQgZXh0cmFjdCB0aGUgcHJlLXByb2Nlc3NlZCB0cmFpbmluZyBkYXRhIG9yIG91ciBwcmUtcHJvY2Vzc2VkIHRlc3RpbmcgZGF0YSB1c2luZyBgYmFrZSgpYC4gV2UgYWxzbyBsZWFybmVkIHRoYXQgaWYgd2UgdXNlZCB0aGUgbmV3ZXIgd29ya2Zsb3dzIHBhY2thZ2UgdGhhdCB3ZSBkaWQgbm90IG5lZWQgdG8gdXNlIHRoZSBgcHJlcCgpYCBvciBgYmFrZSgpYCBmdW5jdGlvbnMsIGJ1dCB0aGF0IGl0IGlzIHN0aWxsIHVzZWZ1bCB0byBrbm93IGhvdyB0byBkbyBzbyBpZiB3ZSB3YW50IHRvIGxvb2sgYXQgb3VyIGRhdGEgYW5kIGhvdyB0aGUgcmVjaXBlIGlzIGluZmx1ZW5jaW5nIGl0IG1vcmUgZGVlcGx5LiAgDQoNCjQuIE1vZGVsIHNwZWNpZmljYXRpb24sIGZpdHRpbmcsIHR1bmluZyBhbmQgcGVyZm9ybWFuY2UgZXZhbHVhdGlvbiB1c2luZyB0aGUgdHJhaW5pbmcgZGF0YSAgDQoNCldlIGxlYXJuZWQgdGhhdCB0aGUgbW9kZWwgbmVlZHMgdG8gZmlyc3QgYmUgZml0IHRvIHRoZSB0cmFpbmluZyBkYXRhLiBXZSBsZWFybmVkIHRoYXQgaW4gYm90aCBjbGFzc2lmaWNhdGlvbiBhbmQgcHJlZGljdGlvbiwgdGhlIG1vZGVsIGlzIGZpdCB0byB0aGUgdHJhaW5pbmcgZGF0YSBhbmQgdGhlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBhcmUgdXNlZCB0byBlc3RpbWF0ZSBudW1lcmljIHZhbHVlcyAoaW4gdGhlIGNhc2Ugb2YgcHJlZGljdGlvbikgb3IgY2F0ZWdvcmljYWwgdmFsdWVzIChpbiB0aGUgY2FzZSBvZiBjbGFzc2lmaWNhdGlvbikgb2YgdGhlIG91dGNvbWUgdmFyaWFibGUgb2YgaW50ZXJlc3QuIFdlIGxlYXJuZWQgdGhhdCB3ZSBzcGVjaWZ5IHRoZSBtb2RlbCBhbmQgaXRzIHNwZWNpZmljYXRpb25zIHVzaW5nIHRoZSBgcGFybnNpcGAgcGFja2FnZSBhbmQgdGhhdCB3ZSBhbHNvIHVzZSB0aGlzIHBhY2thZ2UgdG8gZml0IHRoZSBtb2RlbCB1c2luZyB0aGUgYGZpdCgpYCBmdW5jdGlvbi4gV2UgbGVhcm5lZCB0aGF0IGlmIHdlIGp1c3QgdXNlIGBwYXJzbmlwYCB0byBmaXQgdGhlIG1vZGVsLCB0aGVuIHdlIG5lZWQgdG8gdXNlIHRoZSBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKG91dHB1dCBmcm9tIGBiYWtlKClgKS4gV2UgbGVhcm5lZCB0aGF0IHdlIGNhbiB1c2UgdGhlIHJhdyB0cmFpbmluZyBkYXRhIGlmIHdlIHVzZSB0aGUgYHdvcmtmbG93c2AgcGFja2FnZSB0byBjcmVhdGUgYSB3b3JrZmxvdyB0aGF0IHByZS1wcm9jZXNzZXMgb3VyIGRhdGEgZm9yIHVzLiAgIA0KDQpXZSBsZWFybmVkIHRoYXQgaWYgdGhlIG1vZGVsIGZpdHMgd2VsbCB0aGFuIHRoZSBlc3RpbWF0ZWQgdmFsdWVzIHdpbGwgYmUgdmVyeSBzaW1pbGFyIHRvIHRoZSB0cnVlIG91dGNvbWUgdmFyaWFibGUgdmFsdWVzIGluIG91ciB0cmFpbmluZyBkYXRhLiBXZSBsZWFybmVkIHRoYXQgd2UgY2FuIGFzc2VzcyBtb2RlbCBwZXJmb3JtYW5jZSB1c2luZyB0aGUgYHlhcmRzdGlja2AgcGFja2FnZSB3aXRoIHRoZSBgbWV0cmljc2AgZnVuY3RpbyBvciB0aGUgYHR1bmVgIHBhY2thZ2UgYW5kIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIChyZXF1aXJlZCBpZiB1c2luZyBjcm9zcyB2YWxpZGF0aW9uIG9yIHR1bmluZykuIFdlIGFsc28gbGVhcm5lZCB0aGF0IHdlIGNhbiB1c2Ugc3Vic2V0cyBvZiBvdXIgdHJhaW5pbmcgZGF0YSAod2hpY2ggd2UgY3JlYXRlZCB3aXRoIHRoZSBgcnNhbXBsZWAgcGFja2FnZSkgdG8gcGVyZm9ybSBjcm9zcyB2YWxpZGF0aW9uIHRvIGdldCBhIGJldHRlciBlc3RpbWF0ZSBhYm91dCB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIG1vZGVsIHVzaW5nIG91ciB0cmFpbmluZyBkYXRhLCBhcyB3ZSB3YW50IG91ciByZXN1bHRzIHRvIGJlIGdlbmVyYWxpemFibGUgYW5kIHRvIHBlcmZvcm0gd2VsbCB3aXRoIG90aGVyIGRhdGEsIG5vdCBqdXN0IG91ciB0cmFpbmluZyBkYXRhLiBXZSB1c2VkIHRoZSBgZml0X3Jlc2FtcGxlcygpYCBmdW5jdGlvbiBvZiB0aGUgdHVuZSBwYWNrYWdlIHRvIGZpdCBvdXIgbW9kZWwgb24gb3VyIGRpZmZlcmVudCB0cmFpbmluZyBkYXRhIHN1YnNldHMgYW5kIHRoZSBgY29sbGVjdF9tZXRyaWNzKClgIGZ1bmN0aW9uIChhbHNvIG9mIHRoZSBgdHVuZWAgcGFja2FnZSkgdG8gZXZhbHVhdGUgbW9kZWwgcGVyZm9ybWFuY2UgdXNpbmcgdGhlc2Ugc3Vic2V0cy4gIFdlIGFsc28gbGVhcm5lZCB0aGF0IHdlIGNhbiBwb3RlbnRpYWxseSBpbXByb3ZlIG1vZGVsIHBlcmZvcm1hbmNlIGJ5IHR1bmluZyBhc3BlY3RzIGFib3V0IHRoZSBtb2RlbCBjYWxsZWQgW2h5cGVycGFyYW1ldGVyc10oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS9kaWZmZXJlbmNlLWJldHdlZW4tYS1wYXJhbWV0ZXItYW5kLWEtaHlwZXJwYXJhbWV0ZXIvKXt0YXJnZXQ9Il9ibGFuayJ9IHRvIGRldGVybWluZSB0aGUgYmVzdCBvcHRpb24gZm9yIG1vZGVsIHBlcmZvcm1hbmNlLiBXZSBsZWFybmVkIHRoYXQgd2UgY2FuIGRvIHRoaXMgdXNpbmcgdGhlIGB0dW5lYCBhbmQgYGRpYWxzYCBwYWNrYWdlcyBhbmQgZXZhbHVhdGluZyB0aGUgcGVyZm9ybWFuY2Ugb2Ygb3VyIG1vZGVsIHdpdGggdGhlIGRpZmZlcmVudCBoeXBlcnBhcmFtZXRlciBvcHRpb25zIGFuZCBvdXIgdHJhaW5pbmcgZGF0YSBzdWJzZXRzIHRoYXQgd2UgdXNlZCBmb3IgY3Jvc3MgdmFsaWRhdGlvbi4gQWZ0ZXIgd2UgdGVzdGVkIHNldmVyYWwgZGlmZmVyZW50IG1ldGhvZHMgdG8gbW9kZWwgb3VyIGRhdGEsIHdlIGNvbXBhcmVkIHRoZW0gdG8gY2hvb3NlIHRoZSBiZXN0IHBlcmZvcm1pbmcgbW9kZWwgYXMgb3VyIGZpbmFsIG1vZGVsLiAgDQoNCg0KNS4gT3ZlcmFsbCBtb2RlbCBwZXJmb3JtYW5jZSBldmFsdWF0aW9uICANCg0KT25jZSB3ZSBjaG9zZSBvdXIgZmluYWwgbW9kZWwsIHdlIGV2YWx1YXRlZCB0aGUgZmluYWwgbW9kZWwgcGVyZm9ybWFuY2UgdXNpbmcgdGhlIHRlc3RpbmcgZGF0YSB1c2luZyB0aGUgYGxhc3RfZml0KClgIGZ1bmN0aW9uIG9mIHRoZSBgdHVuZWAgcGFja2FnZS4gVGhpcyBnaXZlcyB1cyBhIGJldHRlciBlc3RpbWF0ZSBhYm91dCBob3cgd2VsbCB0aGUgbW9kZWwgd2lsbCBwcmVkaWN0IG9yIGNsYXNzaWZ5IHRoZSBvdXRjb21lIHZhcmlhYmxlIG9mIGludGVyZXN0IHdpdGggbmV3IGluZGVwZW5kZW50IGRhdGEuIElkZWFsbHkgb25lIHdvdWxkIGFsc28gcGVyZm9ybSBhbiBldmFsdWF0aW9uIHdpdGggaW5kZXBlbmRlbnQgZGF0YSB0byBwcm92aWRlIGEgc2Vuc2Ugb2YgaG93IGdlbmVyYWxpemFibGUgdGhlIG1vZGVsIGlzIHRvIG90aGVyIGRhdGEgc291cmNlcy4gDQoNCldlIGFsc28gc2F3IHRoYXQgd2UgY2FuIHVzZSB0aGUgYGNvbGxlY3RfcHJlZGljdGlvbnMoKWAgZnVuY3Rpb24gb2YgdGhlIGB0dW5lYCBwYWNrYWdlIHRvIGdldCB0aGUgcHJlZGljdGlvbnMgZm9yIG91ciB0ZXN0IGRhdGEuIFdlIHNhdyB0aGF0IHdlIGNhbiBnZXQgbW9yZSBkZXRhaWxlZCBwcmVkaWN0aW9uIGRhdGEgdXNpbmcgdGhlIGBwcmVkaWN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgcGFyc25pcGAgcGFja2FnZS4NCg0KPC9kZXRhaWxzPg0KDQoNCg0KIyMgKipTdWdnZXN0ZWQgSG9tZXdvcmsqKg0KKioqDQoNClN0dWRlbnRzIGNhbiBwcmVkaWN0IGFpciBwb2xsdXRpb24gbW9uaXRvciB2YWx1ZXMgdXNpbmcgYSBkaWZmZXJlbnQgYWxnb3JpdGhtIGFuZCBwcm92aWRlIGFuIGV4cGxhbmF0aW9uIGZvciBob3cgdGhhdCBhbGdvcml0aG0gd29ya3MgYW5kIHdoeSBpdCBtYXkgYmUgYSBnb29kIGNob2ljZSBmb3IgbW9kZWxpbmcgdGhpcyBkYXRhLg0KDQoNCiMgKipBZGRpdGlvbmFsIEluZm9ybWF0aW9uKioNCioqKg0KDQojIyAqKkhlbHBmdWwgTGlua3MqKg0KKioqDQoNCjEuIEEgcmV2aWV3IG9mIFt0aWR5bW9kZWxzXShodHRwczovL3J2aWV3cy5yc3R1ZGlvLmNvbS8yMDE5LzA2LzE5L2EtZ2VudGxlLWludHJvLXRvLXRpZHltb2RlbHMvKXt0YXJnZXQ9Il9ibGFuayJ9ICANCjIuIEEgW2NvdXJzZSBvbiB0aWR5bW9kZWxzXShodHRwczovL2p1bGlhc2lsZ2UuY29tL2Jsb2cvdGlkeW1vZGVscy1tbC1jb3Vyc2UvKXt0YXJnZXQ9Il9ibGFuayJ9IGJ5IEp1bGlhIFNpbGdlICANCjMuIFtNb3JlIGV4YW1wbGVzLCBleHBsYW5hdGlvbnMsIGFuZCBpbmZvIGFib3V0IHRpZHltb2RlbHMgZGV2ZWxvcG1lbnRdKGh0dHBzOi8vd3d3LnRpZHltb2RlbHMub3JnL2xlYXJuLyl7dGFyZ2V0PSJfYmxhbmsifSBmcm9tIHRoZSBkZXZlbG9wZXJzICANCjQuIEEgZ3VpZGUgZm9yIFtwcmUtcHJvY2Vzc2luZyB3aXRoIHJlY2lwZXNdKGh0dHA6Ly93d3cucmViZWNjYWJhcnRlci5jb20vYmxvZy8yMDE5LTA2LTA2X3ByZV9wcm9jZXNzaW5nLyl7dGFyZ2V0PSJfYmxhbmsifSAgDQo1LiBBIFtndWlkZV0oaHR0cHM6Ly9icmlhdHRlLmdpdGh1Yi5pby9nZ2NvcnIvKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciB1c2luZyBHR2FsbHkgdG8gY3JlYXRlIGNvcnJlbGF0aW9uIHBsb3RzICANCjYuIEEgW2d1aWRlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnL2Jsb2cvMjAxOC8xMS9wYXJzbmlwLTAtMC0xLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgdXNpbmcgcGFyc25pcCB0byB0cnkgZGlmZmVyZW50IGFsZ29yaXRobXMgb3IgZW5naW5lcyAgDQo3LiBBIFtsaXN0IG9mIHJlY2lwZSBmdW5jdGlvbnNdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy9yZWZlcmVuY2UvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgDQo4LiBBIGdyZWF0IGJsb2cgcG9zdCBhYm91dCBbY3Jvc3MgdmFsaWRhdGlvbl0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3RyYWluLXRlc3Qtc3BsaXQtYW5kLWNyb3NzLXZhbGlkYXRpb24taW4tcHl0aG9uLTgwYjYxYmVjYTRiNil7dGFyZ2V0PSJfYmxhbmsifSAgDQo5LiBBIGRpc2N1c3Npb24gYWJvdXQgW2V2YWx1YXRpbmcgbW9kZWwgcGVyZm9ybWFuY2VdKGh0dHBzOi8vbWVkaXVtLmNvbS9AbGltYXZhbGxhbnRpbi9tZXRyaWNzLXRvLW1lYXN1cmUtbWFjaGluZS1sZWFybmluZy1tb2RlbC1wZXJmb3JtYW5jZS1lOGM5NjM2NjU0NzYpe3RhcmdldD0iX2JsYW5rIn0gZm9yIGEgZGVlcGVyIGV4cGxhbmF0aW9uIGFib3V0IGhvdyB0byBldmFsdWF0ZSBtb2RlbCBwZXJmb3JtYW5jZSAgDQoxMC4gW1JTdHVkaW8gY2hlYXRzaGVldHNdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLyl7dGFyZ2V0PSJfYmxhbmsifQ0KMTEuIEFuIFtleHBsYW5hdGlvbl0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL3N1cGVydmlzZWQtdnMtdW5zdXBlcnZpc2VkLWxlYXJuaW5nLTE0ZjY4ZTMyZWE4ZCl7dGFyZ2V0PSJfYmxhbmsifSBvZiBzdXBlcnZpc2VkIHZzIHVuc3VwZXJ2aXNlZCBtYWNoaW5lIGxlYXJuaW5nIGFuZCBiaWFzLXZhcmlhbmNlIHRyYWRlLW9mZi4NCjEyLiBBIHRob3JvdWdoIFtleHBsYW5hdGlvbl0oaHR0cHM6Ly9yb3lhbHNvY2lldHlwdWJsaXNoaW5nLm9yZy9kb2kvMTAuMTA5OC9yc3RhLjIwMTUuMDIwMiM6fjp0ZXh0PVByaW5jaXBhbCUyMGNvbXBvbmVudCUyMGFuYWx5c2lzJTIwKFBDQSklMjBpcyx2YXJpYWJsZXMlMjB0aGF0JTIwc3VjY2Vzc2l2ZWx5JTIwbWF4aW1pemUlMjB2YXJpYW5jZS4pe3RhcmdldD0iX2JsYW5rIn0gb2YgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcy4NCjEzLiBJZiB5b3UgaGF2ZSBhY2Nlc3MsIHRoaXMgaXMgYSBncmVhdCBbZGlzY3Vzc2lvbl0oaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9hYnMvMTAuMTA4MC8wMDAzMTMwNS4xOTg0LjEwNDgzMTgzKXt0YXJnZXQ9Il9ibGFuayJ9ICBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGluZGVwZW5kZW5jZSwgb3J0aG9nb25hbGl0eSwgYW5kIGxhY2sgb2YgY29ycmVsYXRpb24uDQoxNC4gR3JlYXQgW3ZpZGVvIGV4cGxhbmF0aW9uXShodHRwczovL3lvdXR1LmJlL19VVkhuZUJVQlcwKXt0YXJnZXQ9Il9ibGFuayJ9IG9mIFBDQS4gIA0KDQo8dT5UZXJtcyBhbmQgY29uY2VwdHMgY292ZXJlZDo8L3U+ICANCg0KW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gIA0KW0ltcHV0YXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ltcHV0YXRpb25fKHN0YXRpc3RpY3MpKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltUcmFuc2Zvcm1hdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGF0YV90cmFuc2Zvcm1hdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIA0KW0Rpc2NyZXRpemF0aW9uXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaXNjcmV0aXphdGlvbl9vZl9jb250aW51b3VzX2ZlYXR1cmVzKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltEdW1teSBWYXJpYWJsZXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0R1bW15X3ZhcmlhYmxlXyhzdGF0aXN0aWNzKSl7dGFyZ2V0PSJfYmxhbmsifSAgDQpbT25lIEhvdCBFbmNvZGluZ10oaHR0cHM6Ly9tYWNoaW5lbGVhcm5pbmdtYXN0ZXJ5LmNvbS93aHktb25lLWhvdC1lbmNvZGUtZGF0YS1pbi1tYWNoaW5lLWxlYXJuaW5nLyl7dGFyZ2V0PSJfYmxhbmsifSAgDQpbRGF0YSBUeXBlIENvbnZlcnNpb25zXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvaGFibGFyL3ZpZ25ldHRlcy9jb252ZXJ0Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIA0KW0ludGVyYWN0aW9uXShodHRwczovL3N0YXRpc3RpY3NieWppbS5jb20vcmVncmVzc2lvbi9pbnRlcmFjdGlvbi1lZmZlY3RzLyl7dGFyZ2V0PSJfYmxhbmsifSAgDQpbTm9ybWFsaXphdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTm9ybWFsaXphdGlvbl8oc3RhdGlzdGljcykpe3RhcmdldD0iX2JsYW5rIn0gIA0KW0RpbWVuc2lvbmFsaXR5IFJlZHVjdGlvbi9TaWduYWwgRXh0cmFjdGlvbl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGltZW5zaW9uYWxpdHlfcmVkdWN0aW9uKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltSb3cgT3BlcmF0aW9uc10oaHR0cHM6Ly90YXJ0YXJ1cy5vcmcvZ2FyZXRoL21hdGhzL0xpbmVhcl9BbGdlYnJhL3Jvd19vcGVyYXRpb25zLnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgDQpbTmVhciBaZXJvIFZhcmFpbmNlXShodHRwczovL3d3dy5yLWJsb2dnZXJzLmNvbS9uZWFyLXplcm8tdmFyaWFuY2UtcHJlZGljdG9ycy1zaG91bGQtd2UtcmVtb3ZlLXRoZW0vKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltQYXJhbWV0ZXJzIGFuZCBIeXBlcnBhcmFtZXRlcnNdKGh0dHBzOi8vbWFjaGluZWxlYXJuaW5nbWFzdGVyeS5jb20vZGlmZmVyZW5jZS1iZXR3ZWVuLWEtcGFyYW1ldGVyLWFuZC1hLWh5cGVycGFyYW1ldGVyLyl7dGFyZ2V0PSJfYmxhbmsifSAgIA0KW1N1cGVydmlzZWQgYW5kIFVuc3BlcnZpc2VkIExlYXJuaW5nXShodHRwczovL3Rvd2FyZHNkYXRhc2NpZW5jZS5jb20vc3VwZXJ2aXNlZC12cy11bnN1cGVydmlzZWQtbGVhcm5pbmctMTRmNjhlMzJlYThkKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzXShodHRwczovL21lZGl1bS5jb20vQHNhdmFzdGFtaXJrby9wY2EtYS1saW5lYXItdHJhbnNmb3JtYXRpb24tZjhhYWNkNGViMDA3KXt0YXJnZXQ9Il9ibGFuayJ9ICANCltMaW5lYXIgQ29tYmluYXRpb25zXShodHRwczovL3d3dy5tYXRoYm9vdGNhbXBzLmNvbS9saW5lYXItY29tYmluYXRpb25zLXZlY3RvcnMvKXt0YXJnZXQ9Il9ibGFuayJ9ICANCltEZWNpc2lvbiBUcmVlXShodHRwczovL21lZGl1bS5jb20vZ3JleWF0b20vZGVjaXNpb24tdHJlZXMtYS1zaW1wbGUtd2F5LXRvLXZpc3VhbGl6ZS1hLWRlY2lzaW9uLWRjNTA2YTQwM2FlYil7dGFyZ2V0PSJfYmxhbmsifSAgDQpbUmFuZG9tIEZvcmVzdF0oaHR0cHM6Ly90b3dhcmRzZGF0YXNjaWVuY2UuY29tL2RlY2lzaW9uLXRyZWUtZW5zZW1ibGVzLWJhZ2dpbmctYW5kLWJvb3N0aW5nLTI2NmE4YmE2MGZkOSl7dGFyZ2V0PSJfYmxhbmsifSAgDQoNCg0KIDx1PioqUGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6KiogPC91Pg0KDQpQYWNrYWdlICAgfCBVc2UgaW4gdGhpcyBjYXNlIHN0dWR5ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQ0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGENCltyZWFkcl0oaHR0cHM6Ly9yZWFkci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gaW1wb3J0IHRoZSBDU1YgZmlsZSBkYXRhDQpbZHBseXJdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHZpZXcvYXJyYW5nZS9maWx0ZXIvc2VsZWN0L2NvbXBhcmUgc3BlY2lmaWMgc3Vic2V0cyBvZiB0aGUgZGF0YSANCltza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhDQpbc3VtbWFyeXRvb2xzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgaW4gYSBkaWZmZXJlbnQgc3R5bGUNClttYWdyaXR0cl0oaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnL2FydGljbGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHVzZSB0aGUgYCU8PiVgIHBpcHBpbmcgb3BlcmF0b3IgDQpbY29ycnBsb3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3JycGxvdC92aWduZXR0ZXMvY29ycnBsb3QtaW50cm8uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIG1ha2UgbGFyZ2UgY29ycmVsYXRpb24gcGxvdHMNCltHR2FsbHldKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9HR2FsbHkvR0dhbGx5LnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIG1ha2Ugc21hbGxlciBjb3JyZWxhdGlvbiBwbG90cyAgDQpbcnNhbXBsZV0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9yc2FtcGxlL2FydGljbGVzL0Jhc2ljcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIHRlc3RpbmcgYW5kIHRyYWluaW5nIHNldHMgYW5kIHRvIHNwbGl0IHRoZSB0cmFpbmluZyBzZXQgZm9yIGNyb3NzLXZhbGlkYXRpb24gIA0KW3JlY2lwZXNdKGh0dHBzOi8vdGlkeW1vZGVscy5naXRodWIuaW8vcmVjaXBlcy8pe3RhcmdldD0iX2JsYW5rIn0gICB8IHRvIHByZS1wcm9jZXNzIGRhdGEgZm9yIG1vZGVsaW5nIGluIGEgdGlkeSBhbmQgcmVwcm9kdWNpYmxlIHdheSBhbmQgdG8gZXh0cmFjdCBwcmUtcHJvY2Vzc2VkIGRhdGEgKG1ham9yIGZ1bmN0aW9ucyBhcmUgYHJlY2lwZSgpYCAsIGBwcmVwKClgIGFuZCB2YXJpb3VzIHRyYW5zZm9ybWF0aW9uIGBzdGVwXyooKWAgZnVuY3Rpb25zLCBhcyB3ZWxsIGFzIGBiYWtlYCB3aGljaCBleHRyYWN0cyBwcmUtcHJvY2Vzc2VkIHRyYWluaW5nIGRhdGEgKHVzZWQgdG8gcmVxdWlyZSBganVpY2UoKWApIGFuZCBhcHBsaWVzIHJlY2lwZSBwcmVwcm9jZXNzaW5nIHN0ZXBzIHRvIHRlc3RpbmcgZGF0YSkuIFNlZSBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3JlY2lwZXMvcmVjaXBlcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gIGZvciBtb3JlIGluZm8uDQpbcGFyc25pcF0oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby9wYXJzbmlwLyl7dGFyZ2V0PSJfYmxhbmsifSAgIHwgYW4gaW50ZXJmYWNlIHRvIGNyZWF0ZSBtb2RlbHMgKG1ham9yIGZ1bmN0aW9ucyBhcmUgIGBmaXQoKWAsIGBzZXRfZW5naW5lKClgKQ0KW3lhcmRzdGlja10oaHR0cHM6Ly90aWR5bW9kZWxzLmdpdGh1Yi5pby95YXJkc3RpY2svKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBldmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgbW9kZWxzDQpbYnJvb21dKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE4LzA3L2Jyb29tLTAtNS0wLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGdldCB0aWR5IG91dHB1dCBmb3Igb3VyIG1vZGVsIGZpdCBhbmQgcGVyZm9ybWFuY2UNCltnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYWtlIHZpc3VhbGl6YXRpb25zIHdpdGggbXVsdGlwbGUgbGF5ZXJzDQpbZGlhbHNdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvYmxvZy8yMDE5LzEwL2RpYWxzLTAtMC0zLyl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIHNwZWNpZnkgaHlwZXItcGFyYW1ldGVyIHR1bmluZw0KW3R1bmVdKGh0dHBzOi8vdHVuZS50aWR5bW9kZWxzLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIGNyb3NzIHZhbGlkYXRpb24sIHR1bmUgaHlwZXItcGFyYW1ldGVycywgYW5kIGdldCBwZXJmb3JtYW5jZSBtZXRyaWNzDQpbd29ya2Zsb3dzXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvd29ya2Zsb3dzL3ZlcnNpb25zLzAuMS4xKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gY3JlYXRlIG1vZGVsaW5nIHdvcmtmbG93IHRvIHN0cmVhbWxpbmUgdGhlIG1vZGVsaW5nIHByb2Nlc3MNClt2aXBdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXAvdmlwLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGNyZWF0ZSB2YXJpYWJsZSBpbXBvcnRhbmNlIHBsb3RzDQpbcmFuZG9tRm9yZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmFuZG9tRm9yZXN0L3JhbmRvbUZvcmVzdC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBwZXJmb3JtIHRoZSByYW5kb20gZm9yZXN0IGFuYWx5c2lzDQpbZG9QYXJhbGxlbF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2RvUGFyYWxsZWwvZG9QYXJhbGxlbC5wZGYpIHwgdG8gZml0IGNyb3NzIHZhbGlkYXRpb24gc2FtcGxlcyBpbiBwYXJhbGxlbCANCltzdHJpbmdyXShodHRwczovL3N0cmluZ3IudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9zdHJpbmdyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBtYW5pcHVsYXRlIHRoZSB0ZXh0IHRoZSBtYXAgZGF0YQ0KW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzZXBhcmF0ZSBkYXRhIHdpdGhpbiBhIGNvbHVtbiBpbnRvIG11bHRpcGxlIGNvbHVtbnMNCltybmF0dXJhbGVhcnRoXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcm5hdHVyYWxlYXJ0aC9SRUFETUUuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGdldCB0aGUgZ2VvbWV0cnkgZGF0YSBmb3IgdGhlIGVhcnRoIHRvIHBsb3QgdGhlIFVTDQpbbWFwc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hcHMvbWFwcy5wZGYpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBnZXQgbWFwIGRhdGFiYXNlIGRhdGEgYWJvdXQgY291bnRpZXMgdG8gZHJhdyB0aGVtIG9uIG91ciBVUyBtYXANCltzZl0oaHR0cHM6Ly9yLXNwYXRpYWwuZ2l0aHViLmlvL3NmLyl7dGFyZ2V0PSJfYmxhbmsifSAgfCB0byBjb252ZXJ0IHRoZSBtYXAgZGF0YSBpbnRvIGEgZGF0YSBmcmFtZQ0KW2x3Z2VvbV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2x3Z2VvbS9sd2dlb20ucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gdXNlIHRoZSBgc2ZgIGZ1bmN0aW9uIHRvIGNvbnZlcnQgdGhlIG1hcCBnZW9ncmFwaGljYWwgZGF0YQ0KW3JnZW9zXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcmdlb3Mvcmdlb3MucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IHwgdG8gdXNlIGdlb21ldHJ5IGRhdGENCltwYXRjaHdvcmtdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9wYXRjaHdvcmsvcGF0Y2h3b3JrLnBkZil7dGFyZ2V0PSJfYmxhbmsifSB8IHRvIGFsbG93IHBsb3RzIHRvIGJlIGNvbWJpbmVkDQoNCg0KIyMgKipTZXNzaW9uIGluZm8qKg0KKioqDQoNCg0KYGBge3J9DQpzZXNzaW9uSW5mbygpDQpgYGANCg0KDQojIyAqKkFja25vd2xlZGdtZW50cyoqDQoqKioNCg0KDQpXZSB3b3VsZCBsaWtlIHRvIGFja25vd2xlZGdlIFtSb2dlciBQZW5nXShodHRwOi8vd3d3LmJpb3N0YXQuamhzcGguZWR1L35ycGVuZy8pLCBbTWVnYW4gTGF0c2hhd10oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMTcwOC9tZWdhbi13ZWlsLWxhdHNoYXcpLCBhbmQgW0tpcnN0ZW4gS29laGxlcl0oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMjkyOC9raXJzdGVuLWtvZWhsZXIpIGZvciBhc3Npc3RpbmcgaW4gZnJhbWluZyB0aGUgbWFqb3IgZGlyZWN0aW9uIG9mIHRoZSBjYXNlIHN0dWR5Lg0KDQpXZSB3b3VsZCBhbHNvIGxpa2UgdG8gYWNrbm93bGVkZ2UgdGhlIFtCbG9vbWJlcmcgQW1lcmljYW4gSGVhbHRoIEluaXRpYXRpdmVdKGh0dHBzOi8vYW1lcmljYW5oZWFsdGguamh1LmVkdS8pIGZvciBmdW5kaW5nIHRoaXMgd29yay4gDQoNCjxzY3JpcHQ+DQogIGlGcmFtZVJlc2l6ZSh7fSwgIi5pbnRlcmFjdGl2ZSIpOw0KPC9zY3JpcHQ+